This is smbpasswd.c in view mode; [Download] [Up]
/* * 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; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.