krb5-no-dot-20041017
[openafs.git] / src / WINNT / afsd / afskfw.c
index 89d085b..743374a 100644 (file)
@@ -62,6 +62,7 @@
 
 #include <osilog.h>
 #include <rxkad_prototypes.h>   /* for life_to_time */
+#include <afs/ptserver.h>
 
 /*
  * TIMING _____________________________________________________________________
@@ -443,28 +444,65 @@ KFW_cleanup(void)
 
 static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
 
+int
+KFW_use_krb524(void)
+{
+    HKEY parmKey;
+    DWORD code, len;
+    DWORD use524 = 0;
+
+    code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+                         0, KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        len = sizeof(use524);
+        code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+                                (BYTE *) &use524, &len);
+        if (code != ERROR_SUCCESS) {
+            RegCloseKey(parmKey);
+
+            code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+                                 0, KEY_QUERY_VALUE, &parmKey);
+            if (code == ERROR_SUCCESS) {
+                len = sizeof(use524);
+                code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+                                        (BYTE *) &use524, &len);
+                if (code != ERROR_SUCCESS)
+                    use524 = 0;
+            }
+        }
+        RegCloseKey (parmKey);
+    }
+    return use524;
+}
+
 int 
 KFW_is_available(void)
 {
     HKEY parmKey;
-       DWORD code, len;
+    DWORD code, len;
     DWORD enableKFW = 1;
 
     code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
                          0, KEY_QUERY_VALUE, &parmKey);
-    if (code != ERROR_SUCCESS)
-        code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
-                             0, KEY_QUERY_VALUE, &parmKey);
-       if (code == ERROR_SUCCESS) {
+    if (code == ERROR_SUCCESS) {
         len = sizeof(enableKFW);
         code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
                                 (BYTE *) &enableKFW, &len);
         if (code != ERROR_SUCCESS) {
-            enableKFW = 1;
+            RegCloseKey(parmKey);
+
+            code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
+                                 0, KEY_QUERY_VALUE, &parmKey);
+            if (code == ERROR_SUCCESS) {
+                len = sizeof(enableKFW);
+                code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
+                                        (BYTE *) &enableKFW, &len);
+                if (code != ERROR_SUCCESS)
+                    enableKFW = 1;
+            }
         }
         RegCloseKey (parmKey);
-       }
-
+    }
     if ( !enableKFW )
         return FALSE;
 
@@ -889,11 +927,11 @@ KFW_import_windows_lsa(void)
 
     princ_realm = krb5_princ_realm(ctx, princ);
     for ( i=0; i<princ_realm->length; i++ ) {
-               realm[i] = princ_realm->data[i];
+        realm[i] = princ_realm->data[i];
         cell[i] = tolower(princ_realm->data[i]);
     }
-       cell[i] = '\0';
-       realm[i] = '\0';
+    cell[i] = '\0';
+    realm[i] = '\0';
 
     code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
     if ( IsDebuggerPresent() ) {
@@ -1197,23 +1235,25 @@ KFW_AFS_get_cred( char * username,
     if ( lifetime == 0 )
         lifetime = pLeash_get_default_lifetime();
 
-    code = KFW_kinit(ctx, cc, HWND_DESKTOP, 
-                      pname, 
-                      password,
-                      lifetime,
-                      pLeash_get_default_forwardable(),
-                      pLeash_get_default_proxiable(),
-                      pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
-                      pLeash_get_default_noaddresses(),
-                      pLeash_get_default_publicip());
-    if ( IsDebuggerPresent() ) {
-        char message[256];
-        sprintf(message,"KFW_kinit() returns: %d\n",code);
-        OutputDebugString(message);
+    if ( password && password[0] ) {
+        code = KFW_kinit( ctx, cc, HWND_DESKTOP, 
+                          pname, 
+                          password,
+                          lifetime,
+                          pLeash_get_default_forwardable(),
+                          pLeash_get_default_proxiable(),
+                          pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
+                          pLeash_get_default_noaddresses(),
+                          pLeash_get_default_publicip());
+        if ( IsDebuggerPresent() ) {
+            char message[256];
+            sprintf(message,"KFW_kinit() returns: %d\n",code);
+            OutputDebugString(message);
+        }
+        if ( code ) goto cleanup;
+
+        KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
     }
-    if ( code ) goto cleanup;
-                   
-    KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
 
     code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime,smbname);
     if ( IsDebuggerPresent() ) {
@@ -2376,6 +2416,114 @@ KFW_AFS_unlog(void)
     return(0);
 }
 
+
+#define ALLOW_REGISTER 1
+static int
+ViceIDToUsername(char *username, 
+                 char *realm_of_user, 
+                 char *realm_of_cell,
+                 char * cell_to_use,
+                 struct ktc_principal *aclient, 
+                 struct ktc_principal *aserver, 
+                 struct ktc_token *atoken)
+{
+    static char lastcell[MAXCELLCHARS+1] = { 0 };
+    static char confname[512] = { 0 };
+    char username_copy[BUFSIZ];
+    long viceId;                       /* AFS uid of user */
+    int  status = 0;
+#ifdef ALLOW_REGISTER
+    afs_int32 id;
+#endif /* ALLOW_REGISTER */
+
+    if (confname[0] == '\0') {
+        strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
+        confname[sizeof(confname) - 2] = '\0';
+    }
+
+    /*
+     * Talk about DUMB!  It turns out that there is a bug in
+     * pr_Initialize -- even if you give a different cell name
+     * to it, it still uses a connection to a previous AFS server
+     * if one exists.  The way to fix this is to change the
+     * _filename_ argument to pr_Initialize - that forces it to
+     * re-initialize the connection.  We do this by adding and
+     * removing a "/" on the end of the configuration directory name.
+     */
+
+    if (lastcell[0] != '\0' && (strcmp(lastcell, aserver->cell) != 0)) {
+        int i = strlen(confname);
+        if (confname[i - 1] == '/') {
+            confname[i - 1] = '\0';
+        } else {
+            confname[i] = '/';
+            confname[i + 1] = '\0';
+        }
+    }
+
+    strcpy(lastcell, aserver->cell);
+
+    if (!pr_Initialize (0, confname, aserver->cell))
+        status = pr_SNameToId (username, &viceId);
+
+    /*
+     * This is a crock, but it is Transarc's crock, so
+     * we have to play along in order to get the
+     * functionality.  The way the afs id is stored is
+     * as a string in the username field of the token.
+     * Contrary to what you may think by looking at
+     * the code for tokens, this hack (AFS ID %d) will
+     * not work if you change %d to something else.
+     */
+
+    /*
+     * This code is taken from cklog -- it lets people
+     * automatically register with the ptserver in foreign cells
+     */
+
+#ifdef ALLOW_REGISTER
+    if (status == 0) {
+        if (viceId != ANONYMOUSID) {
+#else /* ALLOW_REGISTER */
+            if ((status == 0) && (viceId != ANONYMOUSID))
+#endif /* ALLOW_REGISTER */
+            {
+#ifdef AFS_ID_TO_NAME
+                strncpy(username_copy, username, BUFSIZ);
+                snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
+#endif /* AFS_ID_TO_NAME */
+            }
+#ifdef ALLOW_REGISTER
+        } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
+            id = 0;
+            strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
+            strcpy(aclient->instance, "");
+            strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
+            if (status = ktc_SetToken(aserver, atoken, aclient, 0))
+                return status;
+
+            /*                                    
+             * In case you're wondering, we don't need to change the
+             * filename here because we're still connecting to the
+             * same cell -- we're just using a different authentication
+             * level
+             */
+
+            if (status = pr_Initialize(1L, confname, aserver->cell, 0))
+                return status;
+            if (status = pr_CreateUser(username, &id))
+                return status;
+#ifdef AFS_ID_TO_NAME
+            strncpy(username_copy, username, BUFSIZ);
+            snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
+#endif /* AFS_ID_TO_NAME */
+        }
+    }
+#endif /* ALLOW_REGISTER */
+    return status;
+}
+
+
 int
 KFW_AFS_klog(
     krb5_context alt_ctx,
@@ -2435,10 +2583,10 @@ KFW_AFS_klog(
     memset(ServiceName, '\0', sizeof(ServiceName));
     memset(realm_of_user, '\0', sizeof(realm_of_user));
     memset(realm_of_cell, '\0', sizeof(realm_of_cell));
-       if (cell && cell[0])
-               strcpy(Dmycell, cell);
-       else
-               memset(Dmycell, '\0', sizeof(Dmycell));
+    if (cell && cell[0])
+        strcpy(Dmycell, cell);
+    else
+        memset(Dmycell, '\0', sizeof(Dmycell));
 
     // NULL or empty cell returns information on local cell
     if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
@@ -2464,13 +2612,21 @@ KFW_AFS_klog(
     memset((char *)&increds, 0, sizeof(increds));
 
     code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
-       if (code) {
+    if (code) {
         if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() ) 
         {
             OutputDebugString("Principal Not Found for ccache\n");
         }
         goto skip_krb5_init;
     }
+
+    if ( strchr(krb5_princ_component(ctx,client_principal,0),'.') != NULL )
+    {
+        OutputDebugString("Illegal Principal name contains dot in first component\n");
+        rc = KRB5KRB_ERR_GENERIC;
+        goto cleanup;
+    }
+
     i = krb5_princ_realm(ctx, client_principal)->length;
     if (i > REALM_SZ-1) 
         i = REALM_SZ-1;
@@ -2650,7 +2806,8 @@ KFW_AFS_klog(
          * No need to perform a krb524 translation which is 
          * commented out in the code below
          */
-        if (k5creds->ticket.length > MAXKTCTICKETLEN)
+        if (KFW_use_krb524() ||
+            k5creds->ticket.length > MAXKTCTICKETLEN)
             goto try_krb524d;
 
         memset(&aserver, '\0', sizeof(aserver));
@@ -2715,14 +2872,17 @@ KFW_AFS_klog(
             p[len] = '\0';
         }
 
+        ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, 
+                         &aclient, &aserver, &atoken);
+
         if ( smbname ) {
-            strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
-            aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+            strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
+            aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
         } else {
             aclient.smbname[0] = '\0';
         }
 
-        rc = ktc_SetToken(&aserver, &atoken, &aclient, 0);
+        rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
         if (!rc)
             goto cleanup;   /* We have successfully inserted the token */
 
@@ -2833,14 +2993,17 @@ KFW_AFS_klog(
 
     strcpy(aclient.cell, CellName);
 
+    ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName, 
+                      &aclient, &aserver, &atoken);
+
     if ( smbname ) {
-        strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
-        aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+        strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
+        aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
     } else {
         aclient.smbname[0] = '\0';
     }
 
-    if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0))
+    if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
     {
         KFW_AFS_error(rc, "ktc_SetToken()");
         code = rc;