win32-name-event-objects-20040228
[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 /*
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 {
59         tokenEvent_t *te = malloc(sizeof(tokenEvent_t));
60         te->uuid = uuid;
61         memcpy(te->sessionKey, sessionKey, sizeof(te->sessionKey));
62         lock_ObtainMutex(&tokenEventLock);
63         te->next = tokenEvents;
64         tokenEvents = te;
65         lock_ReleaseMutex(&tokenEventLock);
66 }
67
68 /*
69  * Find a uuid on the list.  If it is there, copy the session key and
70  * destroy the entry, since it is only used once.
71  *
72  * Return TRUE if found, FALSE if not found
73  */
74 BOOL cm_FindTokenEvent(afs_uuid_t uuid, char sessionKey[8])
75 {
76         RPC_STATUS status;
77         tokenEvent_t *te;
78         tokenEvent_t **ltep;
79
80         lock_ObtainMutex(&tokenEventLock);
81         te = tokenEvents;
82         ltep = &tokenEvents;
83         while (te) {
84             if (UuidEqual((UUID *)&uuid, (UUID *)&te->uuid, &status)) {
85                         *ltep = te->next;
86                         lock_ReleaseMutex(&tokenEventLock);
87                         memcpy(sessionKey, te->sessionKey,
88                                 sizeof(te->sessionKey));
89                         free(te);
90                         return TRUE;
91             }
92             ltep = &te->next;
93             te = te->next;
94         }
95         lock_ReleaseMutex(&tokenEventLock);
96         return FALSE;
97 }
98
99 /*
100  * RPC manager entry point vector functions
101  */
102
103 long AFSRPC_SetToken(
104         afs_uuid_t uuid,
105         unsigned char __RPC_FAR sessionKey[8])
106 {
107         cm_RegisterNewTokenEvent(uuid, sessionKey);
108         return 0;
109 }
110
111 long AFSRPC_GetToken(
112         afs_uuid_t uuid,
113         unsigned char __RPC_FAR sessionKey[8])
114 {
115         BOOL found;
116
117         found = cm_FindTokenEvent(uuid, sessionKey);
118         if (!found)
119                 return 1;
120
121         return 0;
122 }
123
124 void __RPC_FAR * __RPC_USER midl_user_allocate (size_t cBytes)
125 {
126         return ((void __RPC_FAR *) malloc(cBytes));
127 }
128
129 void __RPC_USER midl_user_free(void __RPC_FAR * p)
130 {
131         free(p);
132
133
134 void RpcListen()
135 {
136         RPC_STATUS              status;
137         char                    *task;
138         RPC_BINDING_VECTOR      *ptrBindingVector = NULL;
139         BOOLEAN                 ifaceRegistered = FALSE;
140         BOOLEAN                 epRegistered = FALSE;
141
142 #ifdef  NOOSIDEBUGSERVER        /* Use All Protseqs already done in OSI */
143
144         status = RpcServerUseAllProtseqs(1, NULL);
145         if (status != RPC_S_OK) {
146                 task = "Use All Protocol Sequences";
147                 goto cleanup;
148         }
149
150 #endif  /* NOOSIDEBUGSERVER */
151
152         status = RpcServerRegisterIf(afsrpc_v1_0_s_ifspec, NULL, NULL);
153         if (status != RPC_S_OK) {
154                 task = "Register Interface";
155                 goto cleanup;
156         }
157         ifaceRegistered = TRUE;
158
159         status = RpcServerInqBindings(&ptrBindingVector);
160         if (status != RPC_S_OK) {
161                 task = "Inquire Bindings";
162                 goto cleanup;
163         }
164
165         status = RpcServerRegisterAuthInfo(NULL, RPC_C_AUTHN_WINNT, NULL, NULL);
166         if (status != RPC_S_OK) {
167                 task = "Register Authentication Info";
168                 goto cleanup;
169         }
170
171         status = RpcEpRegister(afsrpc_v1_0_s_ifspec, ptrBindingVector,
172                                 NULL, "AFS session key interface");
173         if (status != RPC_S_OK) {
174                 task = "Register Endpoints";
175                 goto cleanup;
176         }
177         epRegistered = TRUE;
178
179         afsi_log("RPC server listening");
180
181         status = RpcServerListen(OSI_MAXRPCCALLS, OSI_MAXRPCCALLS, 0);
182         if (status != RPC_S_OK) {
183                 task = "Server Listen";
184         }
185
186 cleanup:
187         if (epRegistered)
188                 (void) RpcEpUnregister(afsrpc_v1_0_s_ifspec, ptrBindingVector,
189                                         NULL);
190
191         if (ptrBindingVector)
192                 (void) RpcBindingVectorFree(&ptrBindingVector);
193
194         if (ifaceRegistered)
195                 (void) RpcServerUnregisterIf(afsrpc_v1_0_s_ifspec, NULL, FALSE);
196
197         if (status != RPC_S_OK)
198                 afsi_log("RPC problem, code %d for %s", status, task);
199
200         return;
201 }
202
203 long RpcInit()
204 {
205         LONG status = ERROR_SUCCESS;
206         HANDLE listenThread;
207         ULONG listenThreadID = 0;
208
209         lock_InitializeMutex(&tokenEventLock, "token event lock");
210
211         listenThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)RpcListen,
212                                     0, 0, &listenThreadID);
213
214         if (listenThread == NULL) {
215                 status = GetLastError();
216         }
217         CloseHandle(listenThread);
218
219         return status;
220 }