win95-initial-port-20010430
[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 <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();
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                 ltep = &te->next;
92                 te = te->next;
93         }
94         lock_ReleaseMutex(&tokenEventLock);
95         return FALSE;
96 }
97
98 /*
99  * RPC manager entry point vector functions
100  */
101
102 long AFSRPC_SetToken(
103         afs_uuid_t uuid,
104         unsigned char __RPC_FAR sessionKey[8])
105 {
106         cm_RegisterNewTokenEvent(uuid, sessionKey);
107         return 0;
108 }
109
110 long AFSRPC_GetToken(
111         afs_uuid_t uuid,
112         unsigned char __RPC_FAR sessionKey[8])
113 {
114         BOOL found;
115
116         found = cm_FindTokenEvent(uuid, sessionKey);
117         if (!found)
118                 return 1;
119
120         return 0;
121 }
122
123 void __RPC_FAR * __RPC_USER midl_user_allocate (size_t cBytes)
124 {
125         return ((void __RPC_FAR *) malloc(cBytes));
126 }
127
128 void __RPC_USER midl_user_free(void __RPC_FAR * p)
129 {
130         free(p);
131
132
133 void RpcListen()
134 {
135         RPC_STATUS              status;
136         char                    *task;
137         RPC_BINDING_VECTOR      *ptrBindingVector = NULL;
138         BOOLEAN                 ifaceRegistered = FALSE;
139         BOOLEAN                 epRegistered = FALSE;
140
141 #ifdef  NOOSIDEBUGSERVER        /* Use All Protseqs already done in OSI */
142
143         status = RpcServerUseAllProtseqs(1, NULL);
144         if (status != RPC_S_OK) {
145                 task = "Use All Protocol Sequences";
146                 goto cleanup;
147         }
148
149 #endif  /* NOOSIDEBUGSERVER */
150
151         status = RpcServerRegisterIf(afsrpc_v1_0_s_ifspec, NULL, NULL);
152         if (status != RPC_S_OK) {
153                 task = "Register Interface";
154                 goto cleanup;
155         }
156         ifaceRegistered = TRUE;
157
158         status = RpcServerInqBindings(&ptrBindingVector);
159         if (status != RPC_S_OK) {
160                 task = "Inquire Bindings";
161                 goto cleanup;
162         }
163
164         status = RpcServerRegisterAuthInfo(NULL, RPC_C_AUTHN_WINNT, NULL, NULL);
165         if (status != RPC_S_OK) {
166                 task = "Register Authentication Info";
167                 goto cleanup;
168         }
169
170         status = RpcEpRegister(afsrpc_v1_0_s_ifspec, ptrBindingVector,
171                                 NULL, "AFS session key interface");
172         if (status != RPC_S_OK) {
173                 task = "Register Endpoints";
174                 goto cleanup;
175         }
176         epRegistered = TRUE;
177
178         afsi_log("RPC server listening");
179
180         status = RpcServerListen(OSI_MAXRPCCALLS, OSI_MAXRPCCALLS, 0);
181         if (status != RPC_S_OK) {
182                 task = "Server Listen";
183         }
184
185 cleanup:
186         if (epRegistered)
187                 (void) RpcEpUnregister(afsrpc_v1_0_s_ifspec, ptrBindingVector,
188                                         NULL);
189
190         if (ptrBindingVector)
191                 (void) RpcBindingVectorFree(&ptrBindingVector);
192
193         if (ifaceRegistered)
194                 (void) RpcServerUnregisterIf(afsrpc_v1_0_s_ifspec, NULL, FALSE);
195
196         if (status != RPC_S_OK)
197                 afsi_log("RPC problem, code %d for %s", status, task);
198
199         return;
200 }
201
202 long RpcInit()
203 {
204         LONG status = ERROR_SUCCESS;
205         HANDLE listenThread;
206         ULONG listenThreadID = 0;
207
208         lock_InitializeMutex(&tokenEventLock, "token event lock");
209
210         listenThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)RpcListen,
211                                     0, 0, &listenThreadID);
212
213         if (listenThread == NULL) {
214                 status = GetLastError();
215         }
216         CloseHandle(listenThread);
217
218         return status;
219 }