Windows: Improve SMB detection of Local System account
[openafs.git] / src / WINNT / afsd / cm_rpc.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afs/param.h>
11 #include <afs/stds.h>
12
13 #include <windows.h>
14 #include <sddl.h>
15 #include <rpc.h>
16 #include <malloc.h>
17
18 #include <osi.h>
19 #include "afsrpc.h"
20
21 #include "afsd.h"
22 #include "afsd_init.h"
23
24 #include "smb.h"
25
26 #include <rx/rxkad.h>
27
28 /*
29  * The motivation for this whole module is that in transmitting tokens
30  * between applications and the AFS service, we must not send session keys
31  * in the clear.  So the SetToken and GetToken pioctl's also do an RPC using
32  * packet privacy to transmit the session key.  The pioctl() generates a UUID
33  * and sends it down, and the RPC sends down the same UUID, so that the service
34  * can match them up.  A list of session keys, searched by UUID, is maintained.
35  */
36
37 extern void afsi_log(char *pattern, ...);
38
39 typedef struct tokenEvent {
40     clientchar_t *SidString;
41     afs_uuid_t uuid;
42     char sessionKey[8];
43     struct tokenEvent *next;
44 } tokenEvent_t;
45
46 tokenEvent_t *tokenEvents = NULL;
47
48 osi_mutex_t tokenEventLock;
49
50 EVENT_HANDLE rpc_ShutdownEvent = NULL;
51
52 /*
53  * Add a new uuid and session key to the list.
54  */
55 void cm_RegisterNewTokenEvent(
56         afs_uuid_t uuid,
57         char sessionKey[8],
58         clientchar_t *SidString)
59 {
60     tokenEvent_t *te = malloc(sizeof(tokenEvent_t));
61     te->SidString = SidString;
62     te->uuid = uuid;
63     memcpy(te->sessionKey, sessionKey, sizeof(te->sessionKey));
64     lock_ObtainMutex(&tokenEventLock);
65     te->next = tokenEvents;
66     tokenEvents = te;
67     lock_ReleaseMutex(&tokenEventLock);
68 }
69
70 /*
71  * Find a uuid on the list.  If it is there, copy the session key and
72  * destroy the entry, since it is only used once.
73  *
74  * Return TRUE if found, FALSE if not found
75  */
76 BOOL cm_FindTokenEvent(afs_uuid_t uuid, char sessionKey[8], clientchar_t **SidString)
77 {
78     RPC_STATUS status;
79     tokenEvent_t *te;
80     tokenEvent_t **ltep;
81
82     lock_ObtainMutex(&tokenEventLock);
83     te = tokenEvents;
84     ltep = &tokenEvents;
85     while (te) {
86         if (UuidEqual((UUID *)&uuid, (UUID *)&te->uuid, &status)) {
87             *ltep = te->next;
88             lock_ReleaseMutex(&tokenEventLock);
89             memcpy(sessionKey, te->sessionKey,
90                     sizeof(te->sessionKey));
91             if (SidString)
92                 *SidString = te->SidString;
93             else
94                 LocalFree(te->SidString);
95             free(te);
96             return TRUE;
97         }
98         ltep = &te->next;
99         te = te->next;
100     }
101     lock_ReleaseMutex(&tokenEventLock);
102     return FALSE;
103 }
104
105 /*
106  * RPC manager entry point vector functions
107  */
108
109 long AFSRPC_SetToken(
110         afs_uuid_t uuid,
111         unsigned char __RPC_FAR sessionKey[8])
112 {
113     clientchar_t      *secSidString = 0;
114
115     if (RpcImpersonateClient(0) == RPC_S_OK) {
116         HANDLE       hToken = 0;
117         PSID         pSid = 0;
118         DWORD gle = 0;
119         DWORD retlen;
120         TOKEN_STATISTICS tokenStats;
121
122         if (!OpenThreadToken( GetCurrentThread(), TOKEN_READ, FALSE, &hToken)) {
123             gle = GetLastError();
124             goto done;
125         }
126
127         if (!GetTokenInformation( hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &retlen)) {
128             gle = GetLastError();
129             goto done;
130         }
131
132         if (!smb_GetUserSID( hToken, &pSid))
133             goto done;
134
135         if (!ConvertSidToStringSidW(pSid, &secSidString))
136             goto done;
137
138       done:
139         if (hToken)
140             CloseHandle( hToken);
141
142         RpcRevertToSelf();
143     }
144
145     cm_RegisterNewTokenEvent(uuid, sessionKey, secSidString);
146
147     return 0;
148 }
149
150 long AFSRPC_GetToken(
151         afs_uuid_t uuid,
152         unsigned char __RPC_FAR sessionKey[8])
153 {
154     BOOL found;
155
156     found = cm_FindTokenEvent(uuid, sessionKey, NULL);
157     if (!found)
158         return 1;
159
160     return 0;
161 }
162
163 void __RPC_FAR * __RPC_USER midl_user_allocate (size_t cBytes)
164 {
165     return ((void __RPC_FAR *) malloc(cBytes));
166 }
167
168 void __RPC_USER midl_user_free(void __RPC_FAR * p)
169 {
170     free(p);
171
172
173 void RpcListen()
174 {
175     RPC_STATUS          status;
176     char                        *task;
177     RPC_BINDING_VECTOR  *ptrBindingVector = NULL;
178     BOOLEAN                     ifaceRegistered = FALSE;
179     BOOLEAN                     epRegistered = FALSE;
180
181 #ifdef  NOOSIDEBUGSERVER        /* Use All Protseqs already done in OSI */
182
183     status = RpcServerUseAllProtseqs(1, NULL);
184     if (status != RPC_S_OK) {
185         task = "Use All Protocol Sequences";
186         goto cleanup;
187     }
188
189 #endif  /* NOOSIDEBUGSERVER */
190
191     status = RpcServerRegisterIf(afsrpc_v1_0_s_ifspec, NULL, NULL);
192     if (status != RPC_S_OK) {
193         task = "Register Interface";
194         goto cleanup;
195     }
196     ifaceRegistered = TRUE;
197
198     status = RpcServerInqBindings(&ptrBindingVector);
199     if (status != RPC_S_OK) {
200         task = "Inquire Bindings";
201         goto cleanup;
202     }
203
204     status = RpcServerRegisterAuthInfo(NULL, RPC_C_AUTHN_WINNT, NULL, NULL);
205     if (status != RPC_S_OK) {
206         task = "Register Authentication Info";
207         goto cleanup;
208     }
209
210     status = RpcEpRegister(afsrpc_v1_0_s_ifspec, ptrBindingVector,
211                             NULL, "AFS session key interface");
212     if (status != RPC_S_OK) {
213         task = "Register Endpoints";
214         goto cleanup;
215     }
216     epRegistered = TRUE;
217
218     afsi_log("RPC server listening");
219
220     status = RpcServerListen(OSI_MAXRPCCALLS, OSI_MAXRPCCALLS, 0);
221     if (status != RPC_S_OK) {
222         task = "Server Listen";
223     }
224
225 cleanup:
226     if (epRegistered)
227         (void) RpcEpUnregister(afsrpc_v1_0_s_ifspec, ptrBindingVector,
228                                 NULL);
229
230     if (ptrBindingVector)
231         (void) RpcBindingVectorFree(&ptrBindingVector);
232
233     if (ifaceRegistered)
234         (void) RpcServerUnregisterIf(afsrpc_v1_0_s_ifspec, NULL, FALSE);
235
236     if (status != RPC_S_OK)
237         afsi_log("RPC problem, code %d for %s", status, task);
238     else
239         afsi_log("RPC shutdown");
240
241     if (rpc_ShutdownEvent != NULL)
242         thrd_SetEvent(rpc_ShutdownEvent);
243     return;
244 }
245
246 long RpcInit()
247 {
248     LONG status = ERROR_SUCCESS;
249     HANDLE listenThread;
250     ULONG listenThreadID = 0;
251     char * name = "afsd_rpc_ShutdownEvent";
252
253     lock_InitializeMutex(&tokenEventLock, "token event lock",
254                           LOCK_HIERARCHY_TOKEN_EVENT_GLOBAL);
255
256     rpc_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
257     if ( GetLastError() == ERROR_ALREADY_EXISTS )
258         afsi_log("Event Object Already Exists: %s", name);
259
260     listenThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)RpcListen,
261                                 0, 0, &listenThreadID);
262
263     if (listenThread == NULL) {
264         status = GetLastError();
265     }
266     CloseHandle(listenThread);
267
268     return status;
269 }
270
271 void RpcShutdown(void)
272 {
273     RpcMgmtStopServerListening(NULL);
274
275     if (rpc_ShutdownEvent != NULL) {
276         thrd_WaitForSingleObject_Event(rpc_ShutdownEvent, INFINITE);
277         CloseHandle(rpc_ShutdownEvent);
278     }
279 }
280