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