ad4d2a13600904feae5990c7a2d706c0709b84b8
[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 <rpc.h>
15 #include <malloc.h>
16
17 #include <osi.h>
18 #ifndef DJGPP
19 #include "afsrpc.h"
20 #else
21 #include "afsrpc95.h"
22 #endif
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     afs_uuid_t uuid;
44     char sessionKey[8];
45     struct tokenEvent *next;
46 } tokenEvent_t;
47
48 tokenEvent_t *tokenEvents = NULL;
49
50 osi_mutex_t tokenEventLock;
51
52 EVENT_HANDLE rpc_ShutdownEvent = NULL;
53
54 /*
55  * Add a new uuid and session key to the list.
56  */
57 void cm_RegisterNewTokenEvent(
58         afs_uuid_t uuid,
59         char sessionKey[8])
60 {
61     tokenEvent_t *te = malloc(sizeof(tokenEvent_t));
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])
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             free(te);
92             return TRUE;
93         }
94         ltep = &te->next;
95         te = te->next;
96     }
97     lock_ReleaseMutex(&tokenEventLock);
98     return FALSE;
99 }
100
101 /*
102  * RPC manager entry point vector functions
103  */
104
105 long AFSRPC_SetToken(
106         afs_uuid_t uuid,
107         unsigned char __RPC_FAR sessionKey[8])
108 {
109     cm_RegisterNewTokenEvent(uuid, sessionKey);
110     return 0;
111 }
112
113 long AFSRPC_GetToken(
114         afs_uuid_t uuid,
115         unsigned char __RPC_FAR sessionKey[8])
116 {
117     BOOL found;
118
119     found = cm_FindTokenEvent(uuid, sessionKey);
120     if (!found)
121         return 1;
122
123     return 0;
124 }
125
126 void __RPC_FAR * __RPC_USER midl_user_allocate (size_t cBytes)
127 {
128     return ((void __RPC_FAR *) malloc(cBytes));
129 }
130
131 void __RPC_USER midl_user_free(void __RPC_FAR * p)
132 {
133     free(p);
134
135
136 void RpcListen()
137 {
138     RPC_STATUS          status;
139     char                        *task;
140     RPC_BINDING_VECTOR  *ptrBindingVector = NULL;
141     BOOLEAN                     ifaceRegistered = FALSE;
142     BOOLEAN                     epRegistered = FALSE;
143
144 #ifdef  NOOSIDEBUGSERVER        /* Use All Protseqs already done in OSI */
145
146     status = RpcServerUseAllProtseqs(1, NULL);
147     if (status != RPC_S_OK) {
148         task = "Use All Protocol Sequences";
149         goto cleanup;
150     }
151
152 #endif  /* NOOSIDEBUGSERVER */
153
154     status = RpcServerRegisterIf(afsrpc_v1_0_s_ifspec, NULL, NULL);
155     if (status != RPC_S_OK) {
156         task = "Register Interface";
157         goto cleanup;
158     }
159     ifaceRegistered = TRUE;
160
161     status = RpcServerInqBindings(&ptrBindingVector);
162     if (status != RPC_S_OK) {
163         task = "Inquire Bindings";
164         goto cleanup;
165     }
166
167     status = RpcServerRegisterAuthInfo(NULL, RPC_C_AUTHN_WINNT, NULL, NULL);
168     if (status != RPC_S_OK) {
169         task = "Register Authentication Info";
170         goto cleanup;
171     }
172
173     status = RpcEpRegister(afsrpc_v1_0_s_ifspec, ptrBindingVector,
174                             NULL, "AFS session key interface");
175     if (status != RPC_S_OK) {
176         task = "Register Endpoints";
177         goto cleanup;
178     }
179     epRegistered = TRUE;
180
181     afsi_log("RPC server listening");
182
183     status = RpcServerListen(OSI_MAXRPCCALLS, OSI_MAXRPCCALLS, 0);
184     if (status != RPC_S_OK) {
185         task = "Server Listen";
186     }
187
188 cleanup:
189     if (epRegistered)
190         (void) RpcEpUnregister(afsrpc_v1_0_s_ifspec, ptrBindingVector,
191                                 NULL);
192
193     if (ptrBindingVector)
194         (void) RpcBindingVectorFree(&ptrBindingVector);
195
196     if (ifaceRegistered)
197         (void) RpcServerUnregisterIf(afsrpc_v1_0_s_ifspec, NULL, FALSE);
198
199     if (status != RPC_S_OK)
200         afsi_log("RPC problem, code %d for %s", status, task);
201     else
202         afsi_log("RPC shutdown");
203
204     if (rpc_ShutdownEvent != NULL)
205         thrd_SetEvent(rpc_ShutdownEvent);
206     return;
207 }
208
209 long RpcInit()
210 {
211     LONG status = ERROR_SUCCESS;
212     HANDLE listenThread;
213     ULONG listenThreadID = 0;
214     char * name = "afsd_rpc_ShutdownEvent";
215
216     lock_InitializeMutex(&tokenEventLock, "token event lock");
217
218     rpc_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
219     if ( GetLastError() == ERROR_ALREADY_EXISTS )
220         afsi_log("Event Object Already Exists: %s", name);
221
222     listenThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)RpcListen,
223                                 0, 0, &listenThreadID);
224
225     if (listenThread == NULL) {
226         status = GetLastError();
227     }
228     CloseHandle(listenThread);
229
230     return status;
231 }
232
233 void RpcShutdown(void)
234 {
235     RpcMgmtStopServerListening(NULL);
236
237     if (rpc_ShutdownEvent != NULL) {
238         thrd_WaitForSingleObject_Event(rpc_ShutdownEvent, INFINITE);
239         CloseHandle(rpc_ShutdownEvent);
240     }
241 }
242