From d4b9b483df4f91928d1d6e1cf7e14901acc0566a Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 13 Mar 2004 21:07:36 +0000 Subject: [PATCH] mutex-token-access-20040313 This is an initial crack at one of the big problems with the existing AFS client. Multiple processes in a single session or in multiple sessions (terminal server) can step on each others toes. This is because the dual use of RPC and SMB calls to perform operations. Since nothing is done in a single synchronized step, there are plenty of opportunities for data overwrites to occur. The change was to add a Global Mutex within all of the ktc_XXXToken calls. The use of "Global\" prefixed kernel objects are only supported on Win2000 and above. This is fine because this is all we claim to support. But if someone was to decide to run this code on NT4 or Win95 anyway bad things will now happen. This should probably be cleaned up if someone has time. --- src/auth/ktc_nt.c | 193 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 149 insertions(+), 44 deletions(-) diff --git a/src/auth/ktc_nt.c b/src/auth/ktc_nt.c index 12780aee2..b165d8800 100644 --- a/src/auth/ktc_nt.c +++ b/src/auth/ktc_nt.c @@ -46,6 +46,9 @@ static int ForgetOneLocalToken(struct ktc_principal *aserver); static char AFSConfigKeyName[] = "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"; +static char AFSGlobalKTCMutexName[] = "Global\\AFS_KTC_Mutex"; +static char AFSKTCMutexName[] = "AFS_KTC_Mutex"; + /* * Support for RPC's to send and receive session keys * @@ -252,6 +255,7 @@ ktc_SetToken(struct ktc_principal *server, struct ktc_token *token, int code; RPC_STATUS status; afs_uuid_t uuid; + HANDLE ktcMutex = NULL; if (token->ticketLen < MINKTCTICKETLEN || token->ticketLen > MAXKTCTICKETLEN) @@ -342,19 +346,38 @@ ktc_SetToken(struct ktc_principal *server, struct ktc_token *token, memcpy(tp, &uuid, sizeof(uuid)); tp += sizeof(uuid); + #ifndef AFS_WIN95_ENV + ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName); + if ( ktcMutex == NULL ) + return KTC_PIOCTLFAIL; + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( ktcMutex, INFINITE) != WAIT_OBJECT_0 ) { + CloseHandle(ktcMutex); + return KTC_PIOCTLFAIL; + } + } + /* RPC to send session key */ status = send_key(uuid, token->sessionKey.data); if (status != RPC_S_OK) { - if (status == 1) - strcpy(rpcErr, "RPC failure in AFS gateway"); - else - DceErrorInqText(status, rpcErr); - if (status == RPC_S_SERVER_UNAVAILABLE - || status == EPT_S_NOT_REGISTERED) - return KTC_NOCMRPC; - else - return KTC_RPC; + if (status == 1) + strcpy(rpcErr, "RPC failure in AFS gateway"); + else + DceErrorInqText(status, rpcErr); + if (status == RPC_S_SERVER_UNAVAILABLE || + status == EPT_S_NOT_REGISTERED) + { + ReleaseMutex(ktcMutex); + CloseHandle(ktcMutex); + return KTC_NOCMRPC; + } + else + { + ReleaseMutex(ktcMutex); + CloseHandle(ktcMutex); + return KTC_RPC; + } } #endif /* AFS_WIN95_ENV */ @@ -365,18 +388,24 @@ ktc_SetToken(struct ktc_principal *server, struct ktc_token *token, iob.out_size = sizeof(tbuffer); code = pioctl(0, VIOCSETTOK, &iob, 0); + +#ifndef AFS_WIN95_ENV + ReleaseMutex(ktcMutex); + CloseHandle(ktcMutex); +#endif /* AFS_WIN95_ENV */ + if (code) { - if (code == -1) { - if (errno == ESRCH) - return KTC_NOCELL; - else if (errno == ENODEV) - return KTC_NOCM; - else if (errno == EINVAL) - return KTC_INVAL; - else - return KTC_PIOCTLFAIL; - } else - return KTC_PIOCTLFAIL; + if (code == -1) { + if (errno == ESRCH) + return KTC_NOCELL; + else if (errno == ENODEV) + return KTC_NOCM; + else if (errno == EINVAL) + return KTC_INVAL; + else + return KTC_PIOCTLFAIL; + } else + return KTC_PIOCTLFAIL; } return 0; @@ -398,6 +427,7 @@ ktc_GetToken(struct ktc_principal *server, struct ktc_token *token, int code; RPC_STATUS status; afs_uuid_t uuid; + HANDLE ktcMutex = NULL; tp = tbuffer; @@ -422,35 +452,57 @@ ktc_GetToken(struct ktc_principal *server, struct ktc_token *token, iob.out = tbuffer; iob.out_size = sizeof(tbuffer); +#ifndef AFS_WIN95_ENV + ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName); + if ( ktcMutex == NULL ) + return KTC_PIOCTLFAIL; + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( ktcMutex, INFINITE) != WAIT_OBJECT_0 ) { + CloseHandle(ktcMutex); + return KTC_PIOCTLFAIL; + } + } +#endif /* AFS_WIN95_ENV */ + code = pioctl(0, VIOCNEWGETTOK, &iob, 0); if (code) { - if (code == -1) { - if (errno == ESRCH) - return KTC_NOCELL; - else if (errno == ENODEV) - return KTC_NOCM; - else if (errno == EINVAL) - return KTC_INVAL; - else if (errno == EDOM) - return KTC_NOENT; - else - return KTC_PIOCTLFAIL; - } else - return KTC_PIOCTLFAIL; - } -#ifndef AFS_WIN95_ENV /* get rid of RPC for win95 build */ +#ifndef AFS_WIN95_ENV + ReleaseMutex(ktcMutex); + CloseHandle(ktcMutex); +#endif /* AFS_WIN95_ENV */ + if (code == -1) { + if (errno == ESRCH) + return KTC_NOCELL; + else if (errno == ENODEV) + return KTC_NOCM; + else if (errno == EINVAL) + return KTC_INVAL; + else if (errno == EDOM) + return KTC_NOENT; + else + return KTC_PIOCTLFAIL; + } else + return KTC_PIOCTLFAIL; + } + +#ifndef AFS_WIN95_ENV + /* get rid of RPC for win95 build */ /* RPC to receive session key */ status = receive_key(uuid, token->sessionKey.data); + + ReleaseMutex(ktcMutex); + CloseHandle(ktcMutex); + if (status != RPC_S_OK) { - if (status == 1) - strcpy(rpcErr, "RPC failure in AFS gateway"); - else - DceErrorInqText(status, rpcErr); - if (status == RPC_S_SERVER_UNAVAILABLE - || status == EPT_S_NOT_REGISTERED) - return KTC_NOCMRPC; - else - return KTC_RPC; + if (status == 1) + strcpy(rpcErr, "RPC failure in AFS gateway"); + else + DceErrorInqText(status, rpcErr); + if (status == RPC_S_SERVER_UNAVAILABLE + || status == EPT_S_NOT_REGISTERED) + return KTC_NOCMRPC; + else + return KTC_RPC; } #endif /* AFS_WIN95_ENV */ @@ -521,6 +573,19 @@ ktc_ListTokens(int cellNum, int *cellNumP, struct ktc_principal *server) char *tp, *cp; int newIter, ticketLen, temp; int code; + HANDLE ktcMutex = NULL; + +#ifndef AFS_WIN95_ENV + ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName); + if ( ktcMutex == NULL ) + return KTC_PIOCTLFAIL; + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( ktcMutex, INFINITE) != WAIT_OBJECT_0 ) { + CloseHandle(ktcMutex); + return KTC_PIOCTLFAIL; + } + } +#endif /* AFS_WIN95_ENV */ tp = tbuffer; @@ -535,6 +600,12 @@ ktc_ListTokens(int cellNum, int *cellNumP, struct ktc_principal *server) iob.out_size = sizeof(tbuffer); code = pioctl(0, VIOCGETTOK, &iob, 0); + +#ifndef AFS_WIN95_ENV + ReleaseMutex(ktcMutex); + CloseHandle(ktcMutex); +#endif /* AFS_WIN95_ENV */ + if (code) { if (code == -1) { if (errno == ESRCH) @@ -594,11 +665,24 @@ ktc_ForgetToken(struct ktc_principal *server) char tbuffer[1024]; char *tp; int code; + HANDLE ktcMutex = NULL; if (strcmp(server->name, "afs")) { return ForgetOneLocalToken(server); } +#ifndef AFS_WIN95_ENV + ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName); + if ( ktcMutex == NULL ) + return KTC_PIOCTLFAIL; + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( ktcMutex, INFINITE) != WAIT_OBJECT_0 ) { + CloseHandle(ktcMutex); + return KTC_PIOCTLFAIL; + } + } +#endif /* AFS_WIN95_ENV */ + tp = tbuffer; /* cell name */ @@ -612,6 +696,10 @@ ktc_ForgetToken(struct ktc_principal *server) iob.out_size = sizeof(tbuffer); code = pioctl(0, VIOCDELTOK, &iob, 0); +#ifndef AFS_WIN95_ENV + ReleaseMutex(ktcMutex); + CloseHandle(ktcMutex); +#endif /* AFS_WIN95_ENV */ if (code) { if (code == -1) { if (errno == ESRCH) @@ -634,9 +722,22 @@ ktc_ForgetAllTokens() struct ViceIoctl iob; char tbuffer[1024]; int code; + HANDLE ktcMutex = NULL; (void)ForgetLocalTokens(); +#ifndef AFS_WIN95_ENV + ktcMutex = CreateMutex(NULL, TRUE, AFSGlobalKTCMutexName); + if ( ktcMutex == NULL ) + return KTC_PIOCTLFAIL; + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( ktcMutex, INFINITE) != WAIT_OBJECT_0 ) { + CloseHandle(ktcMutex); + return KTC_PIOCTLFAIL; + } + } +#endif /* AFS_WIN95_ENV */ + /* do pioctl */ iob.in = tbuffer; iob.in_size = 0; @@ -644,6 +745,10 @@ ktc_ForgetAllTokens() iob.out_size = sizeof(tbuffer); code = pioctl(0, VIOCDELALLTOK, &iob, 0); +#ifndef AFS_WIN95_ENV + ReleaseMutex(ktcMutex); + CloseHandle(ktcMutex); +#endif /* AFS_WIN95_ENV */ if (code) { if (code == -1) { if (errno == ENODEV) -- 2.39.5