home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Networking / SambaManager / samba-1.9.17p4 / source / netinfo / smbpasswd.c < prev   
Encoding:
C/C++ Source or Header  |  1998-03-30  |  10.3 KB  |  391 lines

  1. /*
  2.  * This is the code to change the samba password in netinfo. It completely 
  3.  * replaces the original samba code. Using -a will change/set the samba/NT
  4.  * as well as the unix password. Otherwise only the samba/NT passwords will 
  5.  * be set. Calling this program as passwd implies -a.
  6.  *
  7.  */
  8.  
  9. #include "netinfodef.h"
  10.  
  11. /* The utility routine. */
  12. ni_status ni_search_for_dir(char *dir, char *baseDomain, void **handle, ni_id *id, int timeout, int willwrite, int freeold);
  13.  
  14. /*
  15.  * Print command usage on stderr and die.
  16.  */
  17. static void usage(char *name)
  18. {
  19.     if ( *name == 's' )
  20.         fprintf(stderr, "Usage is : %s [-a] [username]\n", name);
  21.     else
  22.         fprintf(stderr, "Usage is : %s [username]\n", name);
  23.     exit(1);
  24. }
  25.  
  26. int main(int argc, char **argv)
  27. {
  28.  
  29. ni_name                  user_name;
  30. ni_status                status;
  31. ni_id                        ndir;
  32. ni_property            prop;
  33. ni_proplist            props;
  34. void                        *handle;
  35. char                        *ldir;
  36.  
  37. int                            i,j, PropListLen;
  38. int                 real_uid;
  39. int                            smb_only = 1;
  40. int                            next_arg = 1;
  41. struct passwd        *pwd;
  42.  
  43. int                            passwd_index = -1;
  44. int                            smbpasswd_index = -1;
  45. int                            smbntpasswd_index = -1;
  46.  
  47. char                         smbpwd[16];
  48. char                         smbntpwd[16];
  49.  
  50. fstring         old_passwd;
  51. uchar           old_p16[16];
  52. ni_name                    old_unixpasswd;
  53.  
  54. fstring         new_passwd;
  55. uchar           new_p16[16];
  56. ni_name                    new_unixpasswd;
  57. uchar           new_nt_p16[16];
  58. ni_name                    new_p32;
  59. ni_name                    new_nt_p32;
  60.  
  61. char           *p;
  62.  
  63. struct timeval    tp;
  64. struct timezone    tzp;
  65.  
  66.     /*
  67.      * Inititialize the strings and character sets.
  68.      */
  69.     old_unixpasswd = (ni_name)malloc(sizeof(char)*14);
  70.     new_unixpasswd = (ni_name)malloc(sizeof(char)*14);
  71.     new_p32 = (ni_name)malloc(sizeof(char)*34);
  72.     new_nt_p32 = (ni_name)malloc(sizeof(char)*34);
  73.     user_name = (ni_name)malloc(sizeof(char)*256);
  74.     charset_initialise();
  75.  
  76.     /* Implied -a flag? */
  77.     if ((p = strrchr(argv[0], '/')) != NULL)
  78.         p++;
  79.     else
  80.         p = argv[0];
  81.     
  82.     if ( *p != 's' )
  83.         smb_only = 0;
  84.     else if ((argc > 1) && !strcmp(argv[1],"-a")) {
  85.         smb_only = 0;
  86.         next_arg++;
  87.     }
  88.  
  89.   /* Get the real uid */
  90.   real_uid = getuid();
  91.  
  92.   /* If we are root we can change another's password. */
  93.   if (real_uid == 0) { 
  94.     if ((argc - next_arg) > 1)
  95.       usage(argv[0]);
  96.         if (next_arg < argc) {
  97.             i = (strlen(argv[next_arg]) < 255)?strlen(argv[next_arg]):255;
  98.         (void)strncpy(user_name, argv[next_arg], i);
  99.         user_name[i] = '\0';
  100.         } else
  101.             (void)strcpy(user_name, "root");
  102.   } else {
  103.         if (argc - next_arg)
  104.         usage(argv[0]);
  105.     pwd = getpwuid(real_uid);
  106.       if (pwd == NULL) {
  107.         fprintf(stderr, "%s: Unable to get UNIX password entry.\n", argv[0]);
  108.         exit(1);
  109.       }
  110.         (void)strncpy(user_name, pwd->pw_name, strlen(pwd->pw_name)+1);
  111.     }
  112.  
  113.  
  114.  
  115.  
  116.  
  117.     /*
  118.      * Find the user's entry in NetInfo. We will use the first entry found
  119.      * in the hierarchy.
  120.      */
  121.      
  122.     /* Set the directory to get. */
  123.     ldir = (char *)malloc(sizeof(char)*(8+strlen(user_name)));
  124.     (void)strcpy(ldir, "/users/");
  125.     (void)strcat(ldir, user_name);
  126.     
  127.     /*
  128.      * Scan the NetInfo hierarchy, starting from the local level,
  129.      * until either an entry is found or we are past the top level.
  130.      */
  131.     handle = NULL;
  132.     status = ni_search_for_dir(ldir, ".", &handle, &ndir, 5, 1, 1);
  133.     free(ldir);
  134.  
  135.     if (status != NI_OK) {
  136.     fprintf(stderr, "%s: Unable to connect to NetInfo.\n", argv[0]);
  137.         exit(1);
  138.     }
  139.  
  140.     /*
  141.      * Set the sesson to this user unless we are root.
  142.      */
  143.      if (real_uid != 0) {
  144.         status = ni_setuser(handle, user_name);
  145.         if (status != NI_OK) {
  146.             fprintf(stderr, "%s: Unable to set the user to %s.\n", argv[0], user_name);
  147.             ni_free(handle);
  148.             exit(1);
  149.         }
  150.     }
  151.  
  152.     /* Read the directory and all its properties, set the indexes of all entries. */
  153.     status = ni_read(handle, &ndir, &props);
  154.     if (status != NI_OK) {
  155.         ni_free(handle);
  156.         fprintf(stderr, "%s: Unable to get netinfo entry for user %s.\n", argv[0], user_name);
  157.         exit(1);
  158.     }            
  159.  
  160. #define PWENTNAME(pos)     props.ni_proplist_val[pos].nip_name
  161. #define PWENTVALU(pos)     (props.ni_proplist_val[pos].nip_val.ni_namelist_len>0)? \
  162.                           props.ni_proplist_val[pos].nip_val.ni_namelist_val[0]:""
  163.  
  164.     *smbpwd = '\0';
  165.     *smbntpwd = '\0';
  166.  
  167.     for (i = 0; i < props.ni_proplist_len; i++) {
  168.         if (!strcmp(PWENTNAME(i), S_PASSWD))
  169.             passwd_index = i;
  170.         else if (!strcmp(PWENTNAME(i), S_SMBPASSWD)) {
  171.             smbpasswd_index = i;
  172.             /*
  173.                     If the password starts with 'X' or '*', the entry has been disabled. 
  174.                     If it starts with NO PASSWORD, then no password is required.
  175.                     If it starts with the user's name, then no old password is required.
  176.             */
  177.             if ((*(PWENTVALU(i)) == '*') || (*(PWENTVALU(i)) == 'X')) {
  178.                 strncpy((char *)smbpwd, PWENTVALU(i), sizeof(smbpwd)-1);
  179.                 smbpwd[sizeof(smbpwd)-1] = '\0';
  180.             } else if (strncasecmp(PWENTVALU(i), "NO PASSWORD", 11) &&
  181.                                  strncmp(PWENTVALU(i), user_name, strlen(user_name)))
  182.                 ni_decrypt(PWENTVALU(i), (char *)smbpwd);
  183.         } else if (!strcmp(PWENTNAME(i), S_SMBNTPASSWD)) {
  184.             smbntpasswd_index = i;
  185.         }
  186. #ifdef TEST        
  187.         printf("property: %-24s", PWENTNAME(i));
  188.         for (j = 0; j < props.ni_proplist_val[i].nip_val.ni_namelist_len; j++)
  189.             printf("%s%s", j>0?",":"", props.ni_proplist_val[i].nip_val.ni_namelist_val[j]);
  190.         printf("\n");
  191. #endif
  192.     }
  193.  
  194.     ni_proplist_free(&props);
  195.     
  196.     /* Start the dialog. */
  197.     printf("Changing%s for %s.\n", smb_only?" samba password":" passwords", user_name);
  198.  
  199.         
  200.     
  201.   /* 
  202.      * If we are root or the old smb password starts with 'NO PASSWORD'
  203.      * or dosn't exist, (*smbpwd == '\0'), and the unix password
  204.      * isn't to be set we don't ask for the old password.
  205.      */
  206.      
  207. #ifdef TEST
  208.   printf("real_uid: %d\n",real_uid);
  209.     printf("smb_only: %d\n",smb_only);
  210. #endif
  211.      
  212.   old_passwd[0] = '\0';
  213. //  if ((real_uid != 0) && ((*smbpwd != '\0') || !smb_only)) {
  214.   if (real_uid) {
  215.         p = getpass("Unix password:");
  216.         strncpy(old_passwd, p, sizeof(fstring));
  217.         old_passwd[sizeof(fstring)-1] = '\0';
  218.         /* Encrypt the unix password. */
  219.         strncpy(new_unixpasswd, pwd->pw_passwd, 2);    /* copy the old salt */
  220.         new_unixpasswd[2] = '\0';
  221.         memset(old_unixpasswd, '\0', 14);
  222.         strncpy(old_unixpasswd, crypt(old_passwd, new_unixpasswd), 13);
  223.  
  224.         /* Bail out if the old password isn't identical to the stored one. */
  225.         if (memcmp(old_unixpasswd, pwd->pw_passwd, strlen(old_unixpasswd))) {
  226.             ni_free(handle);
  227.             printf("Sorry.\n");
  228.             exit(1);
  229.         }
  230.         status = ni_setpassword(handle, old_passwd);
  231.         if (status != NI_OK) {
  232.             fprintf(stderr, "%s: Unable to set the password of user%s.\n", argv[0], user_name);
  233.             ni_free(handle);
  234.             exit(1);
  235.         }
  236.     }
  237.     
  238.  
  239.     /* 
  240.      *Get a new password and verify.
  241.      */
  242.     new_passwd[0] = '\0';
  243.     if (!smb_only)
  244.         p = getpass("New password:");
  245.     else
  246.         p = getpass("New samba password:");
  247.  
  248.     while ((*p != '\0') && (strlen(p) < 6)) {
  249.         fprintf(stderr, "Please use a longer password.\n", argv[0]);
  250.         p = getpass("New password:");
  251.     }
  252.  
  253.     strncpy(new_passwd, p, sizeof(fstring));
  254.     new_passwd[sizeof(fstring)-1] = '\0';
  255.  
  256.   if (new_passwd[0] == '\0') {
  257.     printf("Password unchanged\n");
  258.         ni_free(handle);
  259.     exit(1);
  260.   }
  261.  
  262.     if (!smb_only)
  263.         p = getpass("Retype new password:");
  264.     else
  265.         p = getpass("Retype new samba password:");
  266.     if (strncmp(p, new_passwd, sizeof(fstring)-1)) {
  267.         fprintf(stderr, "%s: Mismatch - passwords unchanged.\n", argv[0]);
  268.         ni_free(handle);
  269.         exit(1);
  270.     }
  271.  
  272.     /*
  273.      * The new password has been verified. If we have to set the unix password,
  274.      * pick a new salt, then encrypt. Encrypt the samba passwords.
  275.      */
  276.      
  277.      if (!smb_only) {
  278.     char    sa[64] = {'a','b','c','d','e','f','g','h','i','j','k','l','m',
  279.                                     'n','o','p','q','r','s','t','u','v','w','x','y','z',
  280.                                     'A','B','C','D','E','F','G','H','I','J','K','L','M',
  281.                                     'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  282.                                     '0','1','2','3','4','5','6','7','8','9','.','/'},
  283.                 salt[3];
  284.     
  285.         /* Have to pick a new salt! */
  286.         if (gettimeofday(&tp, &tzp) != 0) {
  287.             perror(argv[0]);
  288.             ni_free(handle);
  289.             exit(1);
  290.         }
  291.         
  292.         (void) srandom(tp.tv_sec);
  293.         salt[0] = sa[random()%54];
  294.         salt[1] = sa[random()%54];
  295.         salt[2] = '\0';
  296.         
  297.         
  298.       memset(new_unixpasswd, '\0', 14);
  299.         strncpy(new_unixpasswd, crypt(new_passwd, salt), 13);
  300.     }
  301.     
  302.   memset(new_nt_p16, '\0', 16);
  303.   E_md4hash((uchar *) new_passwd, new_nt_p16);
  304.   
  305.   /* Mangle the passwords into Lanman format */
  306.   new_passwd[14] = '\0';
  307.   strupper(new_passwd);
  308.  
  309.   /*
  310.    * Calculate the SMB (lanman) hash functions of new password.
  311.    */  
  312.   memset(new_p16, '\0', 16);
  313.   E_P16((uchar *) new_passwd, new_p16);
  314.  
  315.  
  316.   /*
  317.    * If we get here either we were root or the old password checked out
  318.    * ok.
  319.    */
  320.  
  321.   /* Create the 32 byte representation of the new p16 */
  322.     ni_encrypt(new_p16, new_p32);
  323.  
  324.   /* Create the 32 byte representation of the new NT md4 hash */
  325.     ni_encrypt(new_nt_p16, new_nt_p32);
  326.  
  327. #ifdef TEST
  328.     if (!smb_only)
  329.         printf("New unix password (encrypted) : %s\n",new_unixpasswd);
  330.     printf("New samba password (encrypted): %s\n", new_p32);
  331.     printf("New NT password (encrypted)   : %s\n", new_nt_p32);
  332. #endif
  333.  
  334.     /* 
  335.      * Now write (back) to NetInfo. As the session password may have been set,
  336.      * we must write the unix password last! 
  337.      * If the samba password entries don't exist and we are root, create them!
  338.      */    
  339.     
  340.     PropListLen = props.ni_proplist_len;
  341.  
  342.     prop.nip_val.ni_namelist_len = 1;
  343.     prop.nip_val.ni_namelist_val = &new_p32;
  344.  
  345.     if (smbpasswd_index >= 0) 
  346.         status = ni_writeprop(handle, &ndir, smbpasswd_index, prop.nip_val); 
  347.     else {
  348.         prop.nip_name = S_SMBPASSWD;
  349.         status = ni_createprop(handle, &ndir, prop, PropListLen++);
  350.         if (status == NI_OK) {
  351.             prop.nip_val.ni_namelist_len = 1;
  352.             prop.nip_val.ni_namelist_val = &user_name;
  353.             prop.nip_name = S_SMBPASSWDW;
  354.             status = ni_createprop(handle, &ndir, prop, PropListLen++);
  355.         }
  356.     }
  357.     
  358.     if (status == NI_OK) {
  359.         prop.nip_val.ni_namelist_len = 1;
  360.         prop.nip_val.ni_namelist_val = &new_nt_p32;
  361.     
  362.         if (smbntpasswd_index >= 0)
  363.             status = ni_writeprop(handle, &ndir, smbntpasswd_index, prop.nip_val); 
  364.         else {
  365.             prop.nip_name = S_SMBNTPASSWD;
  366.             status = ni_createprop(handle, &ndir, prop, PropListLen++);
  367.             if (status == NI_OK) {
  368.                 prop.nip_val.ni_namelist_len = 1;
  369.                 prop.nip_val.ni_namelist_val = &user_name;
  370.                 prop.nip_name = S_SMBNTPASSWDW;
  371.                 status = ni_createprop(handle, &ndir, prop, PropListLen++);
  372.             }
  373.         }
  374.     }
  375.  
  376.      if ((status == NI_OK) && (!smb_only) && (passwd_index >= 0)) {
  377.         prop.nip_val.ni_namelist_len = 1;
  378.         prop.nip_val.ni_namelist_val = &new_unixpasswd;
  379.         status = ni_writeprop(handle, &ndir, passwd_index, prop.nip_val); 
  380.     }
  381.     
  382.     if (status != NI_OK) {
  383.         fprintf(stderr, "%s: Unable to write to NetInfo.\n", argv[0]);
  384.         ni_free(handle);
  385.         return 1;
  386.     }
  387.  
  388.     ni_free(handle);
  389.     return 0;
  390. }
  391.