home *** CD-ROM | disk | FTP | other *** search
- /*
- * This is the code to change the samba password in netinfo. It completely
- * replaces the original samba code. Using -a will change/set the samba/NT
- * as well as the unix password. Otherwise only the samba/NT passwords will
- * be set. Calling this program as passwd implies -a.
- *
- */
-
- #include "netinfodef.h"
-
- /* The utility routine. */
- ni_status ni_search_for_dir(char *dir, char *baseDomain, void **handle, ni_id *id, int timeout, int willwrite, int freeold);
-
- /*
- * Print command usage on stderr and die.
- */
- static void usage(char *name)
- {
- if ( *name == 's' )
- fprintf(stderr, "Usage is : %s [-a] [username]\n", name);
- else
- fprintf(stderr, "Usage is : %s [username]\n", name);
- exit(1);
- }
-
- int main(int argc, char **argv)
- {
-
- ni_name user_name;
- ni_status status;
- ni_id ndir;
- ni_property prop;
- ni_proplist props;
- void *handle;
- char *ldir;
-
- int i,j, PropListLen;
- int real_uid;
- int smb_only = 1;
- int next_arg = 1;
- struct passwd *pwd;
-
- int passwd_index = -1;
- int smbpasswd_index = -1;
- int smbntpasswd_index = -1;
-
- char smbpwd[16];
- char smbntpwd[16];
-
- fstring old_passwd;
- uchar old_p16[16];
- ni_name old_unixpasswd;
-
- fstring new_passwd;
- uchar new_p16[16];
- ni_name new_unixpasswd;
- uchar new_nt_p16[16];
- ni_name new_p32;
- ni_name new_nt_p32;
-
- char *p;
-
- struct timeval tp;
- struct timezone tzp;
-
- /*
- * Inititialize the strings and character sets.
- */
- old_unixpasswd = (ni_name)malloc(sizeof(char)*14);
- new_unixpasswd = (ni_name)malloc(sizeof(char)*14);
- new_p32 = (ni_name)malloc(sizeof(char)*34);
- new_nt_p32 = (ni_name)malloc(sizeof(char)*34);
- user_name = (ni_name)malloc(sizeof(char)*256);
- charset_initialise();
-
- /* Implied -a flag? */
- if ((p = strrchr(argv[0], '/')) != NULL)
- p++;
- else
- p = argv[0];
-
- if ( *p != 's' )
- smb_only = 0;
- else if ((argc > 1) && !strcmp(argv[1],"-a")) {
- smb_only = 0;
- next_arg++;
- }
-
- /* Get the real uid */
- real_uid = getuid();
-
- /* If we are root we can change another's password. */
- if (real_uid == 0) {
- if ((argc - next_arg) > 1)
- usage(argv[0]);
- if (next_arg < argc) {
- i = (strlen(argv[next_arg]) < 255)?strlen(argv[next_arg]):255;
- (void)strncpy(user_name, argv[next_arg], i);
- user_name[i] = '\0';
- } else
- (void)strcpy(user_name, "root");
- } else {
- if (argc - next_arg)
- usage(argv[0]);
- pwd = getpwuid(real_uid);
- if (pwd == NULL) {
- fprintf(stderr, "%s: Unable to get UNIX password entry.\n", argv[0]);
- exit(1);
- }
- (void)strncpy(user_name, pwd->pw_name, strlen(pwd->pw_name)+1);
- }
-
-
-
-
-
- /*
- * Find the user's entry in NetInfo. We will use the first entry found
- * in the hierarchy.
- */
-
- /* Set the directory to get. */
- ldir = (char *)malloc(sizeof(char)*(8+strlen(user_name)));
- (void)strcpy(ldir, "/users/");
- (void)strcat(ldir, user_name);
-
- /*
- * Scan the NetInfo hierarchy, starting from the local level,
- * until either an entry is found or we are past the top level.
- */
- handle = NULL;
- status = ni_search_for_dir(ldir, ".", &handle, &ndir, 5, 1, 1);
- free(ldir);
-
- if (status != NI_OK) {
- fprintf(stderr, "%s: Unable to connect to NetInfo.\n", argv[0]);
- exit(1);
- }
-
- /*
- * Set the sesson to this user unless we are root.
- */
- if (real_uid != 0) {
- status = ni_setuser(handle, user_name);
- if (status != NI_OK) {
- fprintf(stderr, "%s: Unable to set the user to %s.\n", argv[0], user_name);
- ni_free(handle);
- exit(1);
- }
- }
-
- /* Read the directory and all its properties, set the indexes of all entries. */
- status = ni_read(handle, &ndir, &props);
- if (status != NI_OK) {
- ni_free(handle);
- fprintf(stderr, "%s: Unable to get netinfo entry for user %s.\n", argv[0], user_name);
- exit(1);
- }
-
- #define PWENTNAME(pos) props.ni_proplist_val[pos].nip_name
- #define PWENTVALU(pos) (props.ni_proplist_val[pos].nip_val.ni_namelist_len>0)? \
- props.ni_proplist_val[pos].nip_val.ni_namelist_val[0]:""
-
- *smbpwd = '\0';
- *smbntpwd = '\0';
-
- for (i = 0; i < props.ni_proplist_len; i++) {
- if (!strcmp(PWENTNAME(i), S_PASSWD))
- passwd_index = i;
- else if (!strcmp(PWENTNAME(i), S_SMBPASSWD)) {
- smbpasswd_index = i;
- /*
- If the password starts with 'X' or '*', the entry has been disabled.
- If it starts with NO PASSWORD, then no password is required.
- If it starts with the user's name, then no old password is required.
- */
- if ((*(PWENTVALU(i)) == '*') || (*(PWENTVALU(i)) == 'X')) {
- strncpy((char *)smbpwd, PWENTVALU(i), sizeof(smbpwd)-1);
- smbpwd[sizeof(smbpwd)-1] = '\0';
- } else if (strncasecmp(PWENTVALU(i), "NO PASSWORD", 11) &&
- strncmp(PWENTVALU(i), user_name, strlen(user_name)))
- ni_decrypt(PWENTVALU(i), (char *)smbpwd);
- } else if (!strcmp(PWENTNAME(i), S_SMBNTPASSWD)) {
- smbntpasswd_index = i;
- }
- #ifdef TEST
- printf("property: %-24s", PWENTNAME(i));
- for (j = 0; j < props.ni_proplist_val[i].nip_val.ni_namelist_len; j++)
- printf("%s%s", j>0?",":"", props.ni_proplist_val[i].nip_val.ni_namelist_val[j]);
- printf("\n");
- #endif
- }
-
- ni_proplist_free(&props);
-
- /* Start the dialog. */
- printf("Changing%s for %s.\n", smb_only?" samba password":" passwords", user_name);
-
-
-
- /*
- * If we are root or the old smb password starts with 'NO PASSWORD'
- * or dosn't exist, (*smbpwd == '\0'), and the unix password
- * isn't to be set we don't ask for the old password.
- */
-
- #ifdef TEST
- printf("real_uid: %d\n",real_uid);
- printf("smb_only: %d\n",smb_only);
- #endif
-
- old_passwd[0] = '\0';
- // if ((real_uid != 0) && ((*smbpwd != '\0') || !smb_only)) {
- if (real_uid) {
- p = getpass("Unix password:");
- strncpy(old_passwd, p, sizeof(fstring));
- old_passwd[sizeof(fstring)-1] = '\0';
- /* Encrypt the unix password. */
- strncpy(new_unixpasswd, pwd->pw_passwd, 2); /* copy the old salt */
- new_unixpasswd[2] = '\0';
- memset(old_unixpasswd, '\0', 14);
- strncpy(old_unixpasswd, crypt(old_passwd, new_unixpasswd), 13);
-
- /* Bail out if the old password isn't identical to the stored one. */
- if (memcmp(old_unixpasswd, pwd->pw_passwd, strlen(old_unixpasswd))) {
- ni_free(handle);
- printf("Sorry.\n");
- exit(1);
- }
- status = ni_setpassword(handle, old_passwd);
- if (status != NI_OK) {
- fprintf(stderr, "%s: Unable to set the password of user%s.\n", argv[0], user_name);
- ni_free(handle);
- exit(1);
- }
- }
-
-
- /*
- *Get a new password and verify.
- */
- new_passwd[0] = '\0';
- if (!smb_only)
- p = getpass("New password:");
- else
- p = getpass("New samba password:");
-
- while ((*p != '\0') && (strlen(p) < 6)) {
- fprintf(stderr, "Please use a longer password.\n", argv[0]);
- p = getpass("New password:");
- }
-
- strncpy(new_passwd, p, sizeof(fstring));
- new_passwd[sizeof(fstring)-1] = '\0';
-
- if (new_passwd[0] == '\0') {
- printf("Password unchanged\n");
- ni_free(handle);
- exit(1);
- }
-
- if (!smb_only)
- p = getpass("Retype new password:");
- else
- p = getpass("Retype new samba password:");
- if (strncmp(p, new_passwd, sizeof(fstring)-1)) {
- fprintf(stderr, "%s: Mismatch - passwords unchanged.\n", argv[0]);
- ni_free(handle);
- exit(1);
- }
-
- /*
- * The new password has been verified. If we have to set the unix password,
- * pick a new salt, then encrypt. Encrypt the samba passwords.
- */
-
- if (!smb_only) {
- char sa[64] = {'a','b','c','d','e','f','g','h','i','j','k','l','m',
- 'n','o','p','q','r','s','t','u','v','w','x','y','z',
- 'A','B','C','D','E','F','G','H','I','J','K','L','M',
- 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
- '0','1','2','3','4','5','6','7','8','9','.','/'},
- salt[3];
-
- /* Have to pick a new salt! */
- if (gettimeofday(&tp, &tzp) != 0) {
- perror(argv[0]);
- ni_free(handle);
- exit(1);
- }
-
- (void) srandom(tp.tv_sec);
- salt[0] = sa[random()%54];
- salt[1] = sa[random()%54];
- salt[2] = '\0';
-
-
- memset(new_unixpasswd, '\0', 14);
- strncpy(new_unixpasswd, crypt(new_passwd, salt), 13);
- }
-
- memset(new_nt_p16, '\0', 16);
- E_md4hash((uchar *) new_passwd, new_nt_p16);
-
- /* Mangle the passwords into Lanman format */
- new_passwd[14] = '\0';
- strupper(new_passwd);
-
- /*
- * Calculate the SMB (lanman) hash functions of new password.
- */
- memset(new_p16, '\0', 16);
- E_P16((uchar *) new_passwd, new_p16);
-
-
- /*
- * If we get here either we were root or the old password checked out
- * ok.
- */
-
- /* Create the 32 byte representation of the new p16 */
- ni_encrypt(new_p16, new_p32);
-
- /* Create the 32 byte representation of the new NT md4 hash */
- ni_encrypt(new_nt_p16, new_nt_p32);
-
- #ifdef TEST
- if (!smb_only)
- printf("New unix password (encrypted) : %s\n",new_unixpasswd);
- printf("New samba password (encrypted): %s\n", new_p32);
- printf("New NT password (encrypted) : %s\n", new_nt_p32);
- #endif
-
- /*
- * Now write (back) to NetInfo. As the session password may have been set,
- * we must write the unix password last!
- * If the samba password entries don't exist and we are root, create them!
- */
-
- PropListLen = props.ni_proplist_len;
-
- prop.nip_val.ni_namelist_len = 1;
- prop.nip_val.ni_namelist_val = &new_p32;
-
- if (smbpasswd_index >= 0)
- status = ni_writeprop(handle, &ndir, smbpasswd_index, prop.nip_val);
- else {
- prop.nip_name = S_SMBPASSWD;
- status = ni_createprop(handle, &ndir, prop, PropListLen++);
- if (status == NI_OK) {
- prop.nip_val.ni_namelist_len = 1;
- prop.nip_val.ni_namelist_val = &user_name;
- prop.nip_name = S_SMBPASSWDW;
- status = ni_createprop(handle, &ndir, prop, PropListLen++);
- }
- }
-
- if (status == NI_OK) {
- prop.nip_val.ni_namelist_len = 1;
- prop.nip_val.ni_namelist_val = &new_nt_p32;
-
- if (smbntpasswd_index >= 0)
- status = ni_writeprop(handle, &ndir, smbntpasswd_index, prop.nip_val);
- else {
- prop.nip_name = S_SMBNTPASSWD;
- status = ni_createprop(handle, &ndir, prop, PropListLen++);
- if (status == NI_OK) {
- prop.nip_val.ni_namelist_len = 1;
- prop.nip_val.ni_namelist_val = &user_name;
- prop.nip_name = S_SMBNTPASSWDW;
- status = ni_createprop(handle, &ndir, prop, PropListLen++);
- }
- }
- }
-
- if ((status == NI_OK) && (!smb_only) && (passwd_index >= 0)) {
- prop.nip_val.ni_namelist_len = 1;
- prop.nip_val.ni_namelist_val = &new_unixpasswd;
- status = ni_writeprop(handle, &ndir, passwd_index, prop.nip_val);
- }
-
- if (status != NI_OK) {
- fprintf(stderr, "%s: Unable to write to NetInfo.\n", argv[0]);
- ni_free(handle);
- return 1;
- }
-
- ni_free(handle);
- return 0;
- }
-