]> andersk Git - moira.git/commitdiff
Changes from dtanner for password processing for w2k KDC, and some code
authorzacheiss <zacheiss>
Tue, 20 Mar 2001 17:41:55 +0000 (17:41 +0000)
committerzacheiss <zacheiss>
Tue, 20 Mar 2001 17:41:55 +0000 (17:41 +0000)
cleanup.

incremental/winad/setpw.c

index 905e61aa327d7e69c94dda52e226593298b16ce2..85c42867f7ae0064e51132560c5e63da0a411d5c 100644 (file)
@@ -64,13 +64,12 @@ Abstract:
 #include <sys/timeb.h>
 #include <errno.h>
 
-
 #define PW_LENGTH 25
 
 #ifndef krb5_is_krb_error
 #define krb5_is_krb_error(dat)\
-       ((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\
-                                   (dat)->data[0] == 0x5e))
+        ((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\
+        (dat)->data[0] == 0x5e))
 #endif
 
 /* Win32 defines. */
@@ -147,18 +146,18 @@ static int frequency[26][26] =
  */
 
 static int row_sums[26] =
-{796,  160,    284,    401,    1276,   262,    199,    539,    777,    
-  16,  39,     351,    243,    751,    662,    181,    17,     683,    
-  662, 968,    248,    115,    180,    17,     162,    5};
+{796,160,284,401,1276,262,199,539,777, 
+  16,39,351,243,751,662,181,17,683,    
+  662,968,248,115,180,17,162,5};
 
 /*
  * Frequencies of starting characters
  */
 
 static int start_freq [26] =
-{1299, 425,    725,    271,    375,    470,    93,     223,    1009,
- 24,   20,     355,    379,    319,    823,    618,    21,     317,
- 962,  1991,   271,    104,    516,    6,      16,     14};
+{1299,425,725,271,375,470,93,223,1009,
+ 24,20,355,379,319,823,618,21,317,
+ 962,1991,271,104,516,6,16,14};
 
 /*
  * This MUST be equal to the sum of all elements in the above array.
@@ -169,7 +168,7 @@ long myrandom();
 void generate_password(char *password);
 int set_password(char *user, char *domain);
 krb5_error_code encode_krb5_setpw
-       PROTOTYPE((const krb5_setpw *rep, krb5_data ** code));
+  PROTOTYPE((const krb5_setpw *rep, krb5_data ** code));
 krb5_error_code 
 krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
                     struct sockaddr **addr_pp, int *naddrs);
@@ -189,15 +188,15 @@ krb5_error_code krb5_mk_setpw_req(krb5_context context,  krb5_auth_context auth_
   memset (&setpw, 0, sizeof(krb5_setpw));
   if (ret = krb5_auth_con_setflags(context, auth_context,
                                    KRB5_AUTH_CONTEXT_DO_SEQUENCE))
-       return(ret);
+    return(ret);
   setpw.targprinc = targprinc;
   setpw.newpasswd.length = strlen(passwd);
   setpw.newpasswd.data = passwd;
   if ((ret = encode_krb5_setpw(&setpw, &encoded_setpw)))
-         return( ret );
+    return( ret );
   if (ret = krb5_mk_priv(context, auth_context,
-                                          encoded_setpw, &cipherpw, &replay))
-       return(ret);
+                         encoded_setpw, &cipherpw, &replay))
+    return(ret);
   packet->length = 6 + ap_req->length + cipherpw.length;
   packet->data = (char *) malloc(packet->length);
   ptr = packet->data;
@@ -235,97 +234,95 @@ krb5_error_code krb5_rd_setpw_rep(krb5_context context, krb5_auth_context auth_c
   krb5_ap_rep_enc_part *ap_rep_enc;
 
   if (packet->length < 4)
-       return(KRB5KRB_AP_ERR_MODIFIED);
+    return(KRB5KRB_AP_ERR_MODIFIED);
   ptr = packet->data;
   if (krb5_is_krb_error(packet))
     {
-           ret = decode_krb5_error(packet, &krberror);
-           if (ret)
-             return(ret);
-           ret = krberror->error;
-           krb5_free_error(context, krberror);
-           return(ret);
+      ret = decode_krb5_error(packet, &krberror);
+      if (ret)
+        return(ret);
+      ret = krberror->error;
+      krb5_free_error(context, krberror);
+      return(ret);
     }
   /* verify length */
   plen = (*ptr++ & 0xff);
   plen = (plen<<8) | (*ptr++ & 0xff);
   if (plen != packet->length)
-         return(KRB5KRB_AP_ERR_MODIFIED);
+    return(KRB5KRB_AP_ERR_MODIFIED);
   vno = (*ptr++ & 0xff);
   vno = (vno<<8) | (*ptr++ & 0xff);
   if (vno != KRB5_KPASSWD_VERS_SETPW && vno != KRB5_KPASSWD_VERS_CHANGEPW)
-         return(KRB5KDC_ERR_BAD_PVNO);
+    return(KRB5KDC_ERR_BAD_PVNO);
   /* read, check ap-rep length */
   ap_rep.length = (*ptr++ & 0xff);
   ap_rep.length = (ap_rep.length<<8) | (*ptr++ & 0xff);
   if (ptr + ap_rep.length >= packet->data + packet->length)
-         return(KRB5KRB_AP_ERR_MODIFIED);
+    return(KRB5KRB_AP_ERR_MODIFIED);
   if (ap_rep.length)
     {
-           /* verify ap_rep */
-           ap_rep.data = ptr;
-           ptr += ap_rep.length;
-           if (ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc))
-             return(ret);
-           krb5_free_ap_rep_enc_part(context, ap_rep_enc);
-           /* extract and decrypt the result */
-           cipherresult.data = ptr;
-           cipherresult.length = (packet->data + packet->length) - ptr;
-           /* XXX there's no api to do this right. The problem is that
-              if there's a remote subkey, it will be used.  This is
-              not what the spec requires */
-           tmp = auth_context->remote_subkey;
-           auth_context->remote_subkey = NULL;
-           ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
-                                          &replay);
-           auth_context->remote_subkey = tmp;
-           if (ret)
-             return(ret);
+      /* verify ap_rep */
+      ap_rep.data = ptr;
+      ptr += ap_rep.length;
+      if (ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc))
+        return(ret);
+      krb5_free_ap_rep_enc_part(context, ap_rep_enc);
+      /* extract and decrypt the result */
+      cipherresult.data = ptr;
+      cipherresult.length = (packet->data + packet->length) - ptr;
+      /* XXX there's no api to do this right. The problem is that
+         if there's a remote subkey, it will be used.  This is
+         not what the spec requires */
+      tmp = auth_context->remote_subkey;
+      auth_context->remote_subkey = NULL;
+      ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
+                         &replay);
+      auth_context->remote_subkey = tmp;
+      if (ret)
+        return(ret);
     }
   else
     {
-           cipherresult.data = ptr;
-           cipherresult.length = (packet->data + packet->length) - ptr;
-
-           if (ret = krb5_rd_error(context, &cipherresult, &krberror))
-             return(ret);
-
-           clearresult = krberror->e_data;
+      cipherresult.data = ptr;
+      cipherresult.length = (packet->data + packet->length) - ptr;
+      if (ret = krb5_rd_error(context, &cipherresult, &krberror))
+        return(ret);
+      clearresult = krberror->e_data;
     }
   if (clearresult.length < 2)
     {
-           ret = KRB5KRB_AP_ERR_MODIFIED;
-           goto cleanup;
+      ret = KRB5KRB_AP_ERR_MODIFIED;
+      goto cleanup;
     }
   ptr = clearresult.data;
   *result_code = (*ptr++ & 0xff);
   *result_code = (*result_code<<8) | (*ptr++ & 0xff);
   if ((*result_code < KRB5_KPASSWD_SUCCESS) ||
-           (*result_code > KRB5_KPASSWD_ACCESSDENIED))
+      (*result_code > KRB5_KPASSWD_ACCESSDENIED))
     {
-       ret = KRB5KRB_AP_ERR_MODIFIED;
-           goto cleanup;
+      ret = KRB5KRB_AP_ERR_MODIFIED;
+        goto cleanup;
     }
   /* all success replies should be authenticated/encrypted */
   if ((ap_rep.length == 0) && (*result_code == KRB5_KPASSWD_SUCCESS))
     {
-           ret = KRB5KRB_AP_ERR_MODIFIED;
-           goto cleanup;
+      ret = KRB5KRB_AP_ERR_MODIFIED;
+      goto cleanup;
     }
   result_data->length = (clearresult.data + clearresult.length) - ptr;
   if (result_data->length)
     {
-           result_data->data = (char *) malloc(result_data->length);
-           memcpy(result_data->data, ptr, result_data->length);
+      result_data->data = (char *) malloc(result_data->length);
+      memcpy(result_data->data, ptr, result_data->length);
     }
   else
-         result_data->data = NULL;
+    result_data->data = NULL;
   ret = 0;
 cleanup:
   if (ap_rep.length)
-         free(clearresult.data);
+    free(clearresult.data);
   else
-         krb5_free_error(context, krberror);
+    krb5_free_error(context, krberror);
   return(ret);
 }
 
@@ -359,8 +356,8 @@ krb5_error_code krb5_set_password(krb5_context context, krb5_ccache ccache,
   int               tmp_len;
   int               error_count;
   krb5_principal    targprinc;
-  struct timeval    TimeVal;
-  fd_set            readfds;
+  int               count;
+  int               last_count;
 
   auth_context = NULL;
   addr_p = NULL;
@@ -377,7 +374,7 @@ krb5_error_code krb5_set_password(krb5_context context, krb5_ccache ccache,
   memset(userrealm, '\0', sizeof(userrealm));
   targprinc = NULL;
   for (i = 0; i < (int)strlen(domain); i++)
-      userrealm[i] = toupper(domain[i]);
+    userrealm[i] = toupper(domain[i]);
 
   sprintf(temp, "%s@%s", user, userrealm);
   krb5_parse_name(context, temp, &targprinc);
@@ -391,165 +388,121 @@ krb5_error_code krb5_set_password(krb5_context context, krb5_ccache ccache,
   if (code = krb5_get_credentials(context, 0, ccache, &creds, &credsp))
     goto cleanup;
   if (code = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY,
-                                                   NULL, credsp, &ap_req))
+                                  NULL, credsp, &ap_req))
+    goto cleanup;
+  if (code = krb5_locate_kpasswd(context, &targprinc->realm, &addr_p, &out))
     goto cleanup;
- if (code = krb5_locate_kpasswd(context, &targprinc->realm, &addr_p, &out))
-         goto cleanup;
   if (out == 0)
     {     /* Couldn't resolve any KPASSWD names */
       code = 1;
       goto cleanup;
     }
 
-  /* this is really obscure.  s1 is used for all communications.  it
-     is left unconnected in case the server is multihomed and routes
-     are asymmetric.  s2 is connected to resolve routes and get
-     addresses.  this is the *only* way to get proper addresses for
-     multihomed hosts if routing is asymmetric.  
-
-     A related problem in the server, but not the client, is that
-     many os's have no way to disconnect a connected udp socket, so
-     the s2 socket needs to be closed and recreated for each
-     request.  The s1 socket must not be closed, or else queued
-     requests will be lost.
-
-     A "naive" client implementation (one socket, no connect,
-     hostname resolution to get the local ip addr) will work and
-     interoperate if the client is single-homed. */
-
   if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
     {
       free(addr_p);
-           return(errno);
+      return(errno);
     }
   if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
     {
       closesocket(s1);
       free(addr_p);
-           return(errno);
+      return(errno);
     }
   error_count = 0;
   for (i=0; i<out; i++)
     {
-           if (connect(s2, &addr_p[i], sizeof(addr_p[i])) == SOCKET_ERROR)
+      if (connect(s2, &addr_p[i], sizeof(addr_p[i])) == SOCKET_ERROR)
         continue;
-
-           addrlen = sizeof(local_addr);
-       if (getsockname(s2, &local_addr, &addrlen) < 0)
+      addrlen = sizeof(local_addr);
+      if (getsockname(s2, &local_addr, &addrlen) < 0)
         continue;
-           if (((struct sockaddr_in *)&local_addr)->sin_addr.s_addr != 0)
+      if (((struct sockaddr_in *)&local_addr)->sin_addr.s_addr != 0)
         {
-               local_kaddr.addrtype = ADDRTYPE_INET;
-               local_kaddr.length =
-                 sizeof(((struct sockaddr_in *) &local_addr)->sin_addr);
-               local_kaddr.contents = 
-                 (char *) &(((struct sockaddr_in *) &local_addr)->sin_addr);
-             }
+printf("1\n");
+          local_kaddr.addrtype = ADDRTYPE_INET;
+          local_kaddr.length =
+            sizeof(((struct sockaddr_in *) &local_addr)->sin_addr);
+          local_kaddr.contents = 
+            (char *) &(((struct sockaddr_in *) &local_addr)->sin_addr);
+        }
       else
         {
-               krb5_address **addrs;
-               krb5_os_localaddr(context, &addrs);
-               local_kaddr.magic = addrs[0]->magic;
-               local_kaddr.addrtype = addrs[0]->addrtype;
-               local_kaddr.length = addrs[0]->length;
-               local_kaddr.contents = calloc(1, addrs[0]->length);
-               memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
-           krb5_free_addresses(context, addrs);
-             }
-
-           addrlen = sizeof(remote_addr);
-           if (getpeername(s2, &remote_addr, &addrlen) < 0)
-       continue;
-           remote_kaddr.addrtype = ADDRTYPE_INET;
-           remote_kaddr.length =
-             sizeof(((struct sockaddr_in *) &remote_addr)->sin_addr);
-           remote_kaddr.contents = 
-             (char *) &(((struct sockaddr_in *) &remote_addr)->sin_addr);
-           /* mk_priv requires that the local address be set.
-              getsockname is used for this.  rd_priv requires that the
-              remote address be set.  recvfrom is used for this.  If
-              rd_priv is given a local address, and the message has the
-              recipient addr in it, this will be checked.  However, there
-              is simply no way to know ahead of time what address the
-              message will be delivered *to*.  Therefore, it is important
-              that either no recipient address is in the messages when
-              mk_priv is called, or that no local address is passed to
-              rd_priv.  Both is a better idea, and I have done that.  In
-              summary, when mk_priv is called, *only* a local address is
-              specified.  when rd_priv is called, *only* a remote address
-              is specified.  Are we having fun yet?  */
-           if (code = krb5_auth_con_setaddrs(context, auth_context, &local_kaddr, NULL))
+          krb5_address **addrs;
+          krb5_os_localaddr(context, &addrs);
+          local_kaddr.magic = addrs[0]->magic;
+          local_kaddr.addrtype = addrs[0]->addrtype;
+          local_kaddr.length = addrs[0]->length;
+          local_kaddr.contents = calloc(1, addrs[0]->length);
+          memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
+          krb5_free_addresses(context, addrs);
+        }
+
+      addrlen = sizeof(remote_addr);
+      if (getpeername(s2, &remote_addr, &addrlen) < 0)
+         continue;
+      remote_kaddr.addrtype = ADDRTYPE_INET;
+      remote_kaddr.length =
+        sizeof(((struct sockaddr_in *) &remote_addr)->sin_addr);
+      remote_kaddr.contents = 
+        (char *) &(((struct sockaddr_in *) &remote_addr)->sin_addr);
+
+      if (code = krb5_auth_con_setaddrs(context, auth_context, &local_kaddr, NULL))
         goto cleanup;
-           if (code = krb5_mk_setpw_req(context, auth_context, &ap_req,
-                                                   targprinc, newpw, &chpw_req))
+      if (code = krb5_mk_setpw_req(context, auth_context, &ap_req,
+                                   targprinc, newpw, &chpw_req))
         goto cleanup;
-           if ((cc = sendto(s1, chpw_req.data, chpw_req.length, 0,
-                                        (struct sockaddr *) &addr_p[i],
-                                        sizeof(addr_p[i]))) != chpw_req.length)
-        continue; /* try the next addr */
-#ifdef _WIN32
-      krb5_free_data_contents(context, &chpw_req);
-#else
-      free(chpw_req.data);
-#endif
-           chpw_rep.length = 1500;
-           chpw_rep.data = (char *) calloc(1, chpw_rep.length);
-       /* XXX need a timeout/retry loop here */
-           /* "recv" would be good enough here... except that Windows/NT
-              commits the atrocity of returning -1 to indicate failure,
-              but leaving errno set to 0.
-          
-              "recvfrom(...,NULL,NULL)" would seem to be a good enough
-              alternative, and it works on NT, but it doesn't work on
-              SunOS 4.1.4 or Irix 5.3.  Thus we must actually accept the
-              value and discard it. */
-           tmp_len = sizeof(tmp_addr);
-      TimeVal.tv_sec = 10;
-      TimeVal.tv_usec = 0;
-
-      FD_ZERO(&readfds);
-      FD_SET(s1, &readfds);
-      code = select(1, &readfds, NULL, NULL, &TimeVal);
-
-      if ((code == 0) || (code == SOCKET_ERROR))
+
+      if ((cc = sendto(s1, chpw_req.data, chpw_req.length, 0,
+                       (struct sockaddr *) &addr_p[i],
+                       sizeof(addr_p[i]))) != chpw_req.length)
+        continue;
+
+      if (chpw_req.data != NULL)
+        free(chpw_req.data);
+      chpw_rep.length = 1500;
+      chpw_rep.data = (char *) calloc(1, chpw_rep.length);
+
+      tmp_len = sizeof(tmp_addr);
+      last_count = 0;
+      while (1)
         {
-          if (error_count < 2)
+          cc = recvfrom(s1, chpw_rep.data, chpw_rep.length, MSG_PEEK, 
+                        &tmp_addr, &tmp_len);
+          if ((last_count == cc) && (cc != 0))
+            break;
+          last_count = cc;
+          if (cc == 0)
             {
-              closesocket(s1);
-              closesocket(s2);
-              if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
-                goto cleanup;
-              if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
-                goto cleanup;
-              ++error_count;
-              --i;
-              continue;
+              if (last_count == -1)
+                break;
+              last_count = -1;
             }
-          code = errno;
-          goto cleanup;
+          sleep(1);
         }
-           if ((cc = recvfrom(s1, chpw_rep.data, chpw_rep.length, 0, &tmp_addr, &tmp_len)) < 0)
+      if ((cc = recvfrom(s1, chpw_rep.data, chpw_rep.length, 0, &tmp_addr, &tmp_len)) < 0)
         {
           code = errno;
           goto cleanup;
-             }
-           chpw_rep.length = cc;
-           if (code = krb5_auth_con_setaddrs(context, auth_context, NULL,
-                                                                 &remote_kaddr))
+        }
+      chpw_rep.length = cc;
+      if (code = krb5_auth_con_setaddrs(context, auth_context, NULL,
+                                            &remote_kaddr))
         {
           goto cleanup;
-             }
+        }
       local_result_code = 0;
-           code = krb5_rd_setpw_rep(context, auth_context, &chpw_rep,
-                                                &local_result_code, &result_string);
+      code = krb5_rd_setpw_rep(context, auth_context, &chpw_rep,
+                               &local_result_code, &result_string);
 
-           if (result_code)
-             *result_code = local_result_code;
-#ifdef _WIN32
-      krb5_free_data_contents(context, &chpw_req);
-#else
-      free(chpw_req.data);
-#endif
+      if (local_result_code)
+        {
+          if (local_result_code == KRB5_KPASSWD_SOFTERROR)
+            local_result_code = KRB5_KPASSWD_SUCCESS;
+          *result_code = local_result_code;
+        }
+      if (chpw_rep.data != NULL)
+        free(chpw_rep.data);
       break;
 
     }
@@ -561,17 +514,13 @@ cleanup:
   if (auth_context != NULL)
     krb5_auth_con_free(context, auth_context);
   if (ap_req.data != NULL)
-#ifdef _WIN32
-      krb5_free_data_contents(context, &ap_req);
-#else
-      free(ap_req.data);
-#endif
+    free(ap_req.data);
   krb5_free_cred_contents(context, &creds);
   if (credsp != NULL)
     krb5_free_creds(context, credsp);
   if (targprinc != NULL)
     krb5_free_principal(context, targprinc);
-       return(code);
+  return(code);
 }
 
 int set_password(char *user, char *domain)
@@ -580,34 +529,37 @@ int set_password(char *user, char *domain)
   krb5_ccache     ccache;
   int             res_code;
   krb5_error_code retval;
-       char            pw[PW_LENGTH+1];
+  char            pw[PW_LENGTH+1];
 
   if (retval = krb5_init_context(&context))
     return retval;
   if (retval = krb5_cc_default(context, &ccache))
-      return(retval);
+    return(retval);
 
   memset(pw, '\0', sizeof(pw));
   generate_password(pw);
+  res_code = 0;
   retval = krb5_set_password(context, ccache, pw, user, domain, &res_code);
 
-       krb5_cc_close(context, ccache);
-       krb5_free_context(context);
-  return(retval);
+  krb5_cc_close(context, ccache);
+  krb5_free_context(context);
+  if (retval)
+    return(retval);
+  return(res_code);
 }
 
 void generate_password(char *password)
 {
-       int   i;
+  int   i;
   int   j;
   int   row_position;
   int   nchars;
   int   position;
-       int   word;
+  int   word;
   int   line;
-       char  *pwp;
+  char  *pwp;
 
-       for (line = 22; line; --line)
+  for (line = 22; line; --line)
     {
       for (word = 7; word; --word)
         {
@@ -626,7 +578,7 @@ void generate_password(char *password)
             }
           *(++pwp)='\0';
           return;
-                   }
+        }
       putchar('\n');
     }
 }
This page took 0.141295 seconds and 5 git commands to generate.