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.