something-weird-20040402
[openafs.git] / src / auth / ktc_nt.c
index 12780ae..67834d5 100644 (file)
@@ -31,6 +31,8 @@ RCSID
 #include "auth.h"
 #include <afs/afsutil.h>
 
+/* TBUFFERSIZE must be at least 512 larger than KTCMAXTICKETSIZE */
+#define TBUFFERSIZE 8192  
 
 /* Forward declarations for local token cache. */
 static int SetLocalToken(struct ktc_principal *aserver,
@@ -46,6 +48,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
  *
@@ -245,13 +250,14 @@ ktc_SetToken(struct ktc_principal *server, struct ktc_token *token,
             struct ktc_principal *client, int flags)
 {
     struct ViceIoctl iob;
-    char tbuffer[1024];
+    char tbuffer[TBUFFERSIZE];
     char *tp;
     struct ClearToken ct;
     int temp;
     int code;
     RPC_STATUS status;
     afs_uuid_t uuid;
+    HANDLE ktcMutex = NULL;
 
     if (token->ticketLen < MINKTCTICKETLEN
        || token->ticketLen > MAXKTCTICKETLEN)
@@ -342,19 +348,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 +390,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;
@@ -387,7 +418,7 @@ ktc_GetToken(struct ktc_principal *server, struct ktc_token *token,
             int tokenLen, struct ktc_principal *client)
 {
     struct ViceIoctl iob;
-    char tbuffer[1024];
+    char tbuffer[TBUFFERSIZE];
     char *tp, *cp;
     char *ticketP;
     int ticketLen, temp;
@@ -398,6 +429,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 +454,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 */
 
@@ -485,9 +539,8 @@ ktc_GetToken(struct ktc_principal *server, struct ktc_token *token,
     /* user name is here */
 
     /* check that ticket will fit */
-    maxLen = tokenLen - sizeof(struct ktc_token) + MAXKTCTICKETLEN;
-    if (maxLen < ticketLen)
-       return KTC_TOOBIG;
+    if (MAXKTCTICKETLEN < ticketLen)
+               return KTC_TOOBIG;
 
     /* set return values */
     memcpy(token->ticket, ticketP, ticketLen);
@@ -517,10 +570,23 @@ int
 ktc_ListTokens(int cellNum, int *cellNumP, struct ktc_principal *server)
 {
     struct ViceIoctl iob;
-    char tbuffer[1024];
+    char tbuffer[TBUFFERSIZE];
     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 +601,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)
@@ -591,14 +663,27 @@ int
 ktc_ForgetToken(struct ktc_principal *server)
 {
     struct ViceIoctl iob;
-    char tbuffer[1024];
+    char tbuffer[TBUFFERSIZE];
     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 +697,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)
@@ -632,11 +721,24 @@ int
 ktc_ForgetAllTokens()
 {
     struct ViceIoctl iob;
-    char tbuffer[1024];
+    char tbuffer[TBUFFERSIZE];
     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 +746,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)