windows-cell-name-length-consistency-20080806
[openafs.git] / src / WINNT / afsd / afskfw.c
index da84abd..8b53df9 100644 (file)
@@ -667,11 +667,11 @@ KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
         {
             if (cache && *cache != NULL) {
                 pkrb5_cc_close(*ctx, *cache);
-                               *cache = NULL;
-                       }
+                *cache = NULL;
+            }
        
             pkrb5_free_context(*ctx);
-                       *ctx = NULL;
+            *ctx = NULL;
         }
     }
 
@@ -1324,7 +1324,7 @@ KFW_AFS_get_cred( char * username,
     krb5_principal principal = NULL;
     char * pname = NULL;
     krb5_error_code code;
-    char local_cell[MAXCELLCHARS+1];
+    char local_cell[CELL_MAXNAMELEN+1];
     char **cells = NULL;
     int  cell_count=0;
     struct afsconf_cell cellconfig;
@@ -1614,7 +1614,7 @@ KFW_AFS_renew_expiring_tokens(void)
     int cell_count;
     char ** cells=NULL;
     const char * realm = NULL;
-    char local_cell[MAXCELLCHARS+1]="";
+    char local_cell[CELL_MAXNAMELEN+1]="";
     struct afsconf_cell cellconfig;
 
     if (!pkrb5_init_context)
@@ -1742,7 +1742,7 @@ KFW_AFS_renew_token_for_cell(char * cell)
         krb5_ccache                    cc  = 0;
         const char * realm = NULL;
         struct afsconf_cell cellconfig;
-        char local_cell[MAXCELLCHARS+1];
+        char local_cell[CELL_MAXNAMELEN+1];
 
         while ( count-- ) {
             code = pkrb5_parse_name(ctx, principals[count], &princ);
@@ -2658,7 +2658,7 @@ ViceIDToUsername(char *username,
                  struct ktc_principal *aserver, 
                  struct ktc_token *atoken)
 {
-    static char lastcell[MAXCELLCHARS+1] = { 0 };
+    static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
     static char confdir[512] = { 0 };
 #ifdef AFS_ID_TO_NAME
     char username_copy[BUFSIZ];
@@ -2734,6 +2734,25 @@ ViceIDToUsername(char *username,
 }
 
 
+static void
+copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
+    krb5_error_code code;
+    krb5_ticket *ticket;
+    size_t len;
+
+    code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
+    if (code == 0) {
+        len = krb5_princ_realm(context, ticket->server)->length;
+        if (len > destlen - 1)
+            len = destlen - 1;
+
+        strncpy(dest, krb5_princ_realm(context, ticket->server)->data, len);
+        dest[len] = '\0';
+
+        pkrb5_free_ticket(context, ticket);
+    }
+}
+
 int
 KFW_AFS_klog(
     krb5_context alt_ctx,
@@ -2754,8 +2773,8 @@ KFW_AFS_klog(
     struct ktc_principal       aclient;
     char       realm_of_user[REALM_SZ]; /* Kerberos realm of user */
     char       realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
-    char       local_cell[MAXCELLCHARS+1];
-    char       Dmycell[MAXCELLCHARS+1];
+    char       local_cell[CELL_MAXNAMELEN+1];
+    char       Dmycell[CELL_MAXNAMELEN+1];
     struct ktc_token   atoken;
     struct ktc_token   btoken;
     struct afsconf_cell        ak_cellconfig; /* General information about the cell */
@@ -2881,6 +2900,7 @@ KFW_AFS_klog(
     else
         strcpy(CellName, cell);
 
+    /* This is for Kerberos v4 only */
     if (strlen(realm) == 0)
         strcpy(RealmName, realm_of_cell);
     else
@@ -2890,56 +2910,31 @@ KFW_AFS_klog(
 
     if ( try_krb5 ) {
         int len;
+        code = KRB5KRB_ERR_GENERIC;
 
-        /* First try service/cell@REALM */
-        if (code = pkrb5_build_principal(ctx, &increds.server,
-                                          (int)strlen(RealmName),
-                                          RealmName,
-                                          ServiceName,
-                                          CellName,
-                                          0)) 
-        {
-            goto cleanup;
-        }
 
         increds.client = client_principal;
         increds.times.endtime = 0;
         /* Ask for DES since that is what V4 understands */
         increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
 
-
-        if ( IsDebuggerPresent() ) {
-            char * cname, *sname;
-            pkrb5_unparse_name(ctx, increds.client, &cname);
-            pkrb5_unparse_name(ctx, increds.server, &sname);
-            OutputDebugString("Getting tickets for \"");
-            OutputDebugString(cname);
-            OutputDebugString("\" and service \"");
-            OutputDebugString(sname);
-            OutputDebugString("\"\n");
-            pkrb5_free_unparsed_name(ctx,cname);
-            pkrb5_free_unparsed_name(ctx,sname);
-        }
-
-        code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
-        if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
-             code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
-             code == KRB5KRB_AP_ERR_MSG_TYPE) {
-            /* Or service@REALM */
-            pkrb5_free_principal(ctx,increds.server);
+        /* If there was a specific realm we are supposed to try
+         * then use it 
+         */
+        if (strlen(realm) != 0) {
+            /* service/cell@REALM */
             increds.server = 0;
             code = pkrb5_build_principal(ctx, &increds.server,
-                                          (int)strlen(RealmName),
-                                          RealmName,
-                                          ServiceName,
-                                          0);
-
+                                         (int)strlen(realm),
+                                         realm,
+                                         ServiceName,
+                                         CellName,
+                                         0);
             if ( IsDebuggerPresent() ) {
                 char * cname, *sname;
                 pkrb5_unparse_name(ctx, increds.client, &cname);
                 pkrb5_unparse_name(ctx, increds.server, &sname);
-                OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
-                OutputDebugString("Trying again: getting tickets for \"");
+                OutputDebugString("Getting tickets for \"");
                 OutputDebugString(cname);
                 OutputDebugString("\" and service \"");
                 OutputDebugString(sname);
@@ -2950,29 +2945,59 @@ KFW_AFS_klog(
 
             if (!code)
                 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
-        }
 
-        if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
-              code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
-              code == KRB5KRB_AP_ERR_MSG_TYPE) &&
-             strcmp(RealmName, realm_of_cell)) {
-            /* Or service/cell@REALM_OF_CELL */
-            strcpy(RealmName, realm_of_cell);
-            pkrb5_free_principal(ctx,increds.server);
-            increds.server = 0;
-            code = pkrb5_build_principal(ctx, &increds.server,
-                                         (int)strlen(RealmName),
-                                         RealmName,
-                                         ServiceName,
-                                         CellName,
-                                         0);
+            if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+                code == KRB5_ERR_HOST_REALM_UNKNOWN ||
+                code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+                code == KRB5KRB_AP_ERR_MSG_TYPE) {
+                /* Or service@REALM */
+                pkrb5_free_principal(ctx,increds.server);
+                increds.server = 0;
+                code = pkrb5_build_principal(ctx, &increds.server,
+                                              (int)strlen(realm),
+                                              realm,
+                                              ServiceName,
+                                              0);
+
+                if ( IsDebuggerPresent() ) {
+                    char * cname, *sname;
+                    pkrb5_unparse_name(ctx, increds.client, &cname);
+                    pkrb5_unparse_name(ctx, increds.server, &sname);
+                    OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+                    OutputDebugString("Trying again: getting tickets for \"");
+                    OutputDebugString(cname);
+                    OutputDebugString("\" and service \"");
+                    OutputDebugString(sname);
+                    OutputDebugString("\"\n");
+                    pkrb5_free_unparsed_name(ctx,cname);
+                    pkrb5_free_unparsed_name(ctx,sname);
+                }
+
+                if (!code)
+                    code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+            }
+
+            if (code == 0) {
+                /* we have a local realm for the cell */
+                strcpy(realm_of_cell, realm);
+            }
+        } else {
+            /* Otherwise, first try service/cell@CLIENT_REALM */
+            if (code = pkrb5_build_principal(ctx, &increds.server,
+                                              (int)strlen(realm_of_user),
+                                              realm_of_user,
+                                              ServiceName,
+                                              CellName,
+                                              0)) 
+            {
+                goto cleanup;
+            }
 
             if ( IsDebuggerPresent() ) {
                 char * cname, *sname;
                 pkrb5_unparse_name(ctx, increds.client, &cname);
                 pkrb5_unparse_name(ctx, increds.server, &sname);
-                OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
-                OutputDebugString("Trying again: getting tickets for \"");
+                OutputDebugString("Getting tickets for \"");
                 OutputDebugString(cname);
                 OutputDebugString("\" and service \"");
                 OutputDebugString(sname);
@@ -2981,19 +3006,60 @@ KFW_AFS_klog(
                 pkrb5_free_unparsed_name(ctx,sname);
             }
 
-            if (!code)
-                code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+            code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+            if (code == 0) {
+                /* The client's realm is a local realm for the cell.
+                 * Save it so that later the pts registration will not
+                 * be performed.
+                 */
+                strcpy(realm_of_cell, realm_of_user);
+            }
 
-        
-            if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+            if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+                 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
                  code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
-                                code == KRB5KRB_AP_ERR_MSG_TYPE) {
-                /* Or service@REALM_OF_CELL */
+                 code == KRB5KRB_AP_ERR_MSG_TYPE) && 
+                 strcmp(realm_of_user, realm_of_cell)) {
+                /* Then service/cell@CELL_REALM */
+                pkrb5_free_principal(ctx,increds.server);
+                increds.server = 0;
+                code = pkrb5_build_principal(ctx, &increds.server,
+                                              (int)strlen(realm_of_cell),
+                                              realm_of_cell,
+                                              ServiceName,
+                                              CellName,
+                                              0);
+                if ( IsDebuggerPresent() ) {
+                    char * cname, *sname;
+                    pkrb5_unparse_name(ctx, increds.client, &cname);
+                    pkrb5_unparse_name(ctx, increds.server, &sname);
+                    OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+                    OutputDebugString("Trying again: getting tickets for \"");
+                    OutputDebugString(cname);
+                    OutputDebugString("\" and service \"");
+                    OutputDebugString(sname);
+                    OutputDebugString("\"\n");
+                    pkrb5_free_unparsed_name(ctx,cname);
+                    pkrb5_free_unparsed_name(ctx,sname);
+                }
+
+                if (!code)
+                    code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+
+                if (!code && !strlen(realm_of_cell)) 
+                    copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
+            }
+
+            if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+                code == KRB5_ERR_HOST_REALM_UNKNOWN ||
+                code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+                code == KRB5KRB_AP_ERR_MSG_TYPE) {
+                /* Finally service@CELL_REALM */
                 pkrb5_free_principal(ctx,increds.server);
                 increds.server = 0;
                 code = pkrb5_build_principal(ctx, &increds.server,
-                                              (int)strlen(RealmName),
-                                              RealmName,
+                                              (int)strlen(realm_of_cell),
+                                              realm_of_cell,
                                               ServiceName,
                                               0);
 
@@ -3013,6 +3079,8 @@ KFW_AFS_klog(
 
                 if (!code)
                     code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+                if (!code && !strlen(realm_of_cell)) 
+                    copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
             }
         }
 
@@ -3054,7 +3122,7 @@ KFW_AFS_klog(
                 retry++;
                 goto retry_gettoken5;
             }
-            goto try_krb524d;
+            goto cleanup;
         }
 
         if (atoken.kvno == btoken.kvno &&
@@ -3296,7 +3364,7 @@ int
 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
 {
     int        rc;
-    char newcell[MAXCELLCHARS+1];
+    char newcell[CELL_MAXNAMELEN+1];
 
     local_cell[0] = (char)0;
     memset(cellconfig, 0, sizeof(*cellconfig));