/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include #include #include #include #include #include #include #include #include "afsrpc.h" #include "afsd.h" #include "afsd_init.h" #include "smb.h" #include /* * The motivation for this whole module is that in transmitting tokens * between applications and the AFS service, we must not send session keys * in the clear. So the SetToken and GetToken pioctl's also do an RPC using * packet privacy to transmit the session key. The pioctl() generates a UUID * and sends it down, and the RPC sends down the same UUID, so that the service * can match them up. A list of session keys, searched by UUID, is maintained. */ extern void afsi_log(char *pattern, ...); typedef struct tokenEvent { clientchar_t *SidString; afs_uuid_t uuid; char sessionKey[8]; struct tokenEvent *next; } tokenEvent_t; tokenEvent_t *tokenEvents = NULL; osi_mutex_t tokenEventLock; EVENT_HANDLE rpc_ShutdownEvent = NULL; /* * Add a new uuid and session key to the list. */ void cm_RegisterNewTokenEvent( afs_uuid_t uuid, char sessionKey[8], clientchar_t *SidString) { tokenEvent_t *te = malloc(sizeof(tokenEvent_t)); te->SidString = SidString; te->uuid = uuid; memcpy(te->sessionKey, sessionKey, sizeof(te->sessionKey)); lock_ObtainMutex(&tokenEventLock); te->next = tokenEvents; tokenEvents = te; lock_ReleaseMutex(&tokenEventLock); } /* * Find a uuid on the list. If it is there, copy the session key and * destroy the entry, since it is only used once. * * Return TRUE if found, FALSE if not found */ BOOL cm_FindTokenEvent(afs_uuid_t uuid, char sessionKey[8], clientchar_t **SidString) { RPC_STATUS status; tokenEvent_t *te; tokenEvent_t **ltep; lock_ObtainMutex(&tokenEventLock); te = tokenEvents; ltep = &tokenEvents; while (te) { if (UuidEqual((UUID *)&uuid, (UUID *)&te->uuid, &status)) { *ltep = te->next; lock_ReleaseMutex(&tokenEventLock); memcpy(sessionKey, te->sessionKey, sizeof(te->sessionKey)); if (SidString) *SidString = te->SidString; else LocalFree(te->SidString); free(te); return TRUE; } ltep = &te->next; te = te->next; } lock_ReleaseMutex(&tokenEventLock); return FALSE; } /* * RPC manager entry point vector functions */ long AFSRPC_SetToken( afs_uuid_t uuid, unsigned char __RPC_FAR sessionKey[8]) { clientchar_t *secSidString = 0; if (RpcImpersonateClient(0) == RPC_S_OK) { HANDLE hToken = 0; PSID pSid = 0; DWORD gle = 0; DWORD retlen; TOKEN_STATISTICS tokenStats; if (!OpenThreadToken( GetCurrentThread(), TOKEN_READ, FALSE, &hToken)) { gle = GetLastError(); goto done; } if (!GetTokenInformation( hToken, TokenStatistics, &tokenStats, sizeof(tokenStats), &retlen)) { gle = GetLastError(); goto done; } if (!smb_GetUserSID( hToken, &pSid)) goto done; if (!ConvertSidToStringSidW(pSid, &secSidString)) goto done; done: if (hToken) CloseHandle( hToken); RpcRevertToSelf(); } cm_RegisterNewTokenEvent(uuid, sessionKey, secSidString); return 0; } long AFSRPC_GetToken( afs_uuid_t uuid, unsigned char __RPC_FAR sessionKey[8]) { BOOL found; found = cm_FindTokenEvent(uuid, sessionKey, NULL); if (!found) return 1; return 0; } void __RPC_FAR * __RPC_USER midl_user_allocate (size_t cBytes) { return ((void __RPC_FAR *) malloc(cBytes)); } void __RPC_USER midl_user_free(void __RPC_FAR * p) { free(p); } void RpcListen() { RPC_STATUS status; char *task; RPC_BINDING_VECTOR *ptrBindingVector = NULL; BOOLEAN ifaceRegistered = FALSE; BOOLEAN epRegistered = FALSE; #ifdef NOOSIDEBUGSERVER /* Use All Protseqs already done in OSI */ status = RpcServerUseAllProtseqs(1, NULL); if (status != RPC_S_OK) { task = "Use All Protocol Sequences"; goto cleanup; } #endif /* NOOSIDEBUGSERVER */ status = RpcServerRegisterIf(afsrpc_v1_0_s_ifspec, NULL, NULL); if (status != RPC_S_OK) { task = "Register Interface"; goto cleanup; } ifaceRegistered = TRUE; status = RpcServerInqBindings(&ptrBindingVector); if (status != RPC_S_OK) { task = "Inquire Bindings"; goto cleanup; } status = RpcServerRegisterAuthInfo(NULL, RPC_C_AUTHN_WINNT, NULL, NULL); if (status != RPC_S_OK) { task = "Register Authentication Info"; goto cleanup; } status = RpcEpRegister(afsrpc_v1_0_s_ifspec, ptrBindingVector, NULL, "AFS session key interface"); if (status != RPC_S_OK) { task = "Register Endpoints"; goto cleanup; } epRegistered = TRUE; afsi_log("RPC server listening"); status = RpcServerListen(OSI_MAXRPCCALLS, OSI_MAXRPCCALLS, 0); if (status != RPC_S_OK) { task = "Server Listen"; } cleanup: if (epRegistered) (void) RpcEpUnregister(afsrpc_v1_0_s_ifspec, ptrBindingVector, NULL); if (ptrBindingVector) (void) RpcBindingVectorFree(&ptrBindingVector); if (ifaceRegistered) (void) RpcServerUnregisterIf(afsrpc_v1_0_s_ifspec, NULL, FALSE); if (status != RPC_S_OK) afsi_log("RPC problem, code %d for %s", status, task); else afsi_log("RPC shutdown"); if (rpc_ShutdownEvent != NULL) thrd_SetEvent(rpc_ShutdownEvent); return; } long RpcInit() { LONG status = ERROR_SUCCESS; HANDLE listenThread; ULONG listenThreadID = 0; char * name = "afsd_rpc_ShutdownEvent"; lock_InitializeMutex(&tokenEventLock, "token event lock", LOCK_HIERARCHY_TOKEN_EVENT_GLOBAL); rpc_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name); if ( GetLastError() == ERROR_ALREADY_EXISTS ) afsi_log("Event Object Already Exists: %s", name); listenThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)RpcListen, 0, 0, &listenThreadID); if (listenThread == NULL) { status = GetLastError(); } CloseHandle(listenThread); return status; } void RpcShutdown(void) { RpcMgmtStopServerListening(NULL); if (rpc_ShutdownEvent != NULL) { thrd_WaitForSingleObject_Event(rpc_ShutdownEvent, INFINITE); CloseHandle(rpc_ShutdownEvent); } }