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