示例#1
0
文件: net_status.c 项目: gojdic/samba
static int show_session(struct db_record *rec, void *private_data)
{
	bool *parseable = (bool *)private_data;
	struct sessionid sessionid;

	if (rec->value.dsize != sizeof(sessionid))
		return 0;

	memcpy(&sessionid, rec->value.dptr, sizeof(sessionid));

	if (!process_exists(sessionid.pid)) {
		return 0;
	}

	if (*parseable) {
		d_printf("%s\\%s\\%s\\%s\\%s\n",
			 procid_str_static(&sessionid.pid), uidtoname(sessionid.uid),
			 gidtoname(sessionid.gid),
			 sessionid.remote_machine, sessionid.hostname);
	} else {
		d_printf("%7s   %-12s  %-12s  %-12s (%s)\n",
			 procid_str_static(&sessionid.pid), uidtoname(sessionid.uid),
			 gidtoname(sessionid.gid),
			 sessionid.remote_machine, sessionid.hostname);
	}

	return 0;
}
示例#2
0
文件: status.c 项目: aosm/samba
static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
	struct sessionid sessionid;
	fstring uid_str, gid_str;

	if (dbuf.dsize != sizeof(sessionid))
		return 0;

	memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));

	if (!process_exists_by_pid(sessionid.pid) || !Ucrit_checkUid(sessionid.uid)) {
		return 0;
	}

	Ucrit_addPid( sessionid.pid );

	fstr_sprintf(uid_str, "%d", sessionid.uid);
	fstr_sprintf(gid_str, "%d", sessionid.gid);

	d_printf("%5d   %-12s  %-12s  %-12s (%s)\n",
		 (int)sessionid.pid,
		 numeric_only ? uid_str : uidtoname(sessionid.uid),
		 numeric_only ? gid_str : gidtoname(sessionid.gid), 
		 sessionid.remote_machine, sessionid.hostname);
	
	return 0;
}
示例#3
0
static int traverse_sessionid(struct db_record *db, void *state)
{
	struct sessionid sessionid;
	fstring uid_str, gid_str;

	if (db->value.dsize != sizeof(sessionid))
		return 0;

	memcpy(&sessionid, db->value.dptr, sizeof(sessionid));

	if (!process_exists(sessionid.pid) || !Ucrit_checkUid(sessionid.uid)) {
		return 0;
	}

	Ucrit_addPid( sessionid.pid );

	fstr_sprintf(uid_str, "%d", sessionid.uid);
	fstr_sprintf(gid_str, "%d", sessionid.gid);

	d_printf("%-7s   %-12s  %-12s  %-12s (%s)\n",
		 procid_str_static(&sessionid.pid),
		 numeric_only ? uid_str : uidtoname(sessionid.uid),
		 numeric_only ? gid_str : gidtoname(sessionid.gid), 
		 sessionid.remote_machine, sessionid.hostname);
	
	return 0;
}
示例#4
0
static int
fsdirstat(char *path, int dev, Dir *d)
{
	int fd;
	struct stat st;
	
	if(stat(path, &st) < 0 && lstat(path, &st) < 0)
		return -1;

	d->name = lastelem(path);
	d->uid = uidtoname(st.st_uid);
	d->gid = gidtoname(st.st_gid);
	d->muid = "";
	d->qid = fsqid(&st);
	d->mode = (d->qid.type<<24) | (st.st_mode&0777);
	d->atime = st.st_atime;
	d->mtime = st.st_mtime;
	d->length = st.st_size;
	if(S_ISBLK(st.st_mode) && (fd = open(path, O_RDONLY)) >= 0){
		d->length = disksize(fd, &st);
		close(fd);
	}
	
	// devmnt leaves 1-9 unused so that we can steal them.
	// it is easier for all involved if #Z shows M as the file type instead of Z.
	// dev is c->dev, either 1 (#Z) or 2 (#Zplan9).
	d->type = 'M';
	d->dev = dev;
	return 0;
}
示例#5
0
static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
    struct sessionid sessionid;

    if (dbuf.dsize != sizeof(sessionid))
        return 0;

    memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));

    if (!process_exists(sessionid.pid) || !Ucrit_checkUsername(uidtoname(sessionid.uid))) {
        return 0;
    }

    Ucrit_addPid( sessionid.pid );

    d_printf("%5d   %-12s  %-12s  %-12s (%s)\n",
             (int)sessionid.pid, uidtoname(sessionid.uid), gidtoname(sessionid.gid),
             sessionid.remote_machine, sessionid.hostname);

    return 0;
}
示例#6
0
/* traversal fn for showing share connections */
static int traverse_fn3(const struct connections_key *key,
                        const struct connections_data *crec,
                        void *private_data)
{
	if (crec->cnum == -1 || !process_exists(crec->pid))
		return 0;

	printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
	       crec->servicename, uidtoname(crec->uid),
	       gidtoname(crec->gid),procid_str_static(&crec->pid),
	       crec->machine,
	       tstring(talloc_tos(),crec->start));
	return 0;
}
示例#7
0
文件: status.c 项目: srimalik/samba
static bool Ucrit_addPid( struct server_id pid )
{
	if ( !Ucrit_IsActive )
		return True;

	if ( Ucrit_MaxPid >= SMB_MAXPIDS ) {
		d_printf("ERROR: More than %d pids for user %s!\n",
			 SMB_MAXPIDS, uidtoname(Ucrit_uid));

		return False;
	}

	Ucrit_pid[Ucrit_MaxPid++] = pid;

	return True;
}
示例#8
0
void standard_sub_snum(int snum, char *str, size_t len)
{
	extern struct current_user current_user;
	static uid_t cached_uid = -1;
	static fstring cached_user;
	/* calling uidtoname() on every substitute would be too expensive, so
	   we cache the result here as nearly every call is for the same uid */

	if (cached_uid != current_user.uid) {
		fstrcpy(cached_user, uidtoname(current_user.uid));
		cached_uid = current_user.uid;
	}

	standard_sub_advanced(snum, cached_user, "", -1,
			      smb_user_name, str, len);
}
示例#9
0
文件: xml.c 项目: execjosh/tree
void xml_fillinfo(struct _info *ent)
{
  #ifdef __USE_FILE_OFFSET64
  if (inodeflag) fprintf(outfile," inode=\"%lld\"",(long long)ent->inode);
  #else
  if (inodeflag) fprintf(outfile," inode=\"%ld\"",(long int)ent->inode);
  #endif
  if (devflag) fprintf(outfile, " dev=\"%d\"", (int)ent->dev);
  #ifdef __EMX__
  if (pflag) fprintf(outfile, " mode=\"%04o\" prot=\"%s\"",ent->attr, prot(ent->attr));
  #else
  if (pflag) fprintf(outfile, " mode=\"%04o\" prot=\"%s\"", ent->mode & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID|S_ISVTX), prot(ent->mode));
  #endif
  if (uflag) fprintf(outfile, " user=\"%s\"", uidtoname(ent->uid));
  if (gflag) fprintf(outfile, " group=\"%s\"", gidtoname(ent->gid));
  if (sflag) fprintf(outfile, " size=\"%lld\"", (long long int)(ent->size));
  if (Dflag) fprintf(outfile, " time=\"%s\"", do_date(cflag? ent->ctime : ent->mtime));
}
示例#10
0
文件: status.c 项目: aosm/samba
static int traverse_processes(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
	struct sessionid sessionid;
	struct process_id pid;

	if (dbuf.dsize != sizeof(sessionid))
		return 0;
	memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));

	pid = pid_to_procid((pid_t)sessionid.pid);
	if (!process_exists(pid)) {
		return 0;
	}
	Ucrit_addPid( sessionid.pid );
	d_printf("%5d   %-12s  %-12s",
	       (int)sessionid.pid, uidtoname(sessionid.uid), gidtoname(sessionid.gid));
	do_collect_usrstat(pid);
	return 0;
}
示例#11
0
文件: statuspage.c 项目: hajuuk/R7000
/* traversal fn for showing share connections */
static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state)
{
	struct connections_data crec;

	if (dbuf.dsize != sizeof(crec))
		return 0;

	memcpy(&crec, dbuf.dptr, sizeof(crec));

	if (crec.cnum == -1 || !process_exists(crec.pid))
		return 0;

	printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td></tr>\n",
	       crec.name,uidtoname(crec.uid),
	       gidtoname(crec.gid),(int)crec.pid,
	       crec.machine,
	       tstring(crec.start));
	return 0;
}
示例#12
0
void standard_sub_snum(int snum, char *str, size_t len)
{
	static uid_t cached_uid = -1;
	static fstring cached_user;
	char *s;
	
	/* calling uidtoname() on every substitute would be too expensive, so
	   we cache the result here as nearly every call is for the same uid */

	if (cached_uid != current_user.ut.uid) {
		fstrcpy(cached_user, uidtoname(current_user.ut.uid));
		cached_uid = current_user.ut.uid;
	}

	s = alloc_sub_advanced(snum, cached_user, "", current_user.ut.gid,
			      smb_user_name, str);

	if ( s ) {
		strncpy( str, s, len );
		SAFE_FREE( s );
	}
}
示例#13
0
char *fillinfo(char *buf, struct _info *ent)
{
  int n;
  buf[n=0] = 0;
  #ifdef __USE_FILE_OFFSET64
  if (inodeflag) n += sprintf(buf," %7lld",(long long)ent->inode);
  #else
  if (inodeflag) n += sprintf(buf," %7ld",(long int)ent->inode);
  #endif
  if (devflag) n += sprintf(buf+n, " %3d", (int)ent->dev);
  #ifdef __EMX__
  if (pflag) n += sprintf(buf+n, " %s",prot(ent->attr));
  #else
  if (pflag) n += sprintf(buf+n, " %s", prot(ent->mode));
  #endif
  if (uflag) n += sprintf(buf+n, " %-8.32s", uidtoname(ent->uid));
  if (gflag) n += sprintf(buf+n, " %-8.32s", gidtoname(ent->gid));
  if (sflag) n += psize(buf+n,ent->size);
  if (Dflag) n += sprintf(buf+n, " %s", do_date(cflag? ent->ctime : ent->mtime));

  return buf;
}
示例#14
0
文件: status.c 项目: srimalik/samba
static int traverse_sessionid(const char *key, struct sessionid *session,
			      void *private_data)
{
	fstring uid_str, gid_str;

	if (!process_exists(session->pid)
	    || !Ucrit_checkUid(session->uid)) {
		return 0;
	}

	Ucrit_addPid(session->pid);

	fstr_sprintf(uid_str, "%u", (unsigned int)session->uid);
	fstr_sprintf(gid_str, "%u", (unsigned int)session->gid);

	d_printf("%-7s   %-12s  %-12s  %-12s (%s)\n",
		 procid_str_static(&session->pid),
		 numeric_only ? uid_str : uidtoname(session->uid),
		 numeric_only ? gid_str : gidtoname(session->gid),
		 session->remote_machine, session->hostname);

	return 0;
}
示例#15
0
static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
    struct connections_data crec;

    if (dbuf.dsize != sizeof(crec))
        return 0;

    memcpy(&crec, dbuf.dptr, sizeof(crec));

    if (crec.cnum == -1)
        return 0;

    if (!process_exists(crec.pid) || !Ucrit_checkUsername(uidtoname(crec.uid))) {
        return 0;
    }

    d_printf("%-10.10s   %5d   %-12s  %s",
             crec.name,(int)crec.pid,
             crec.machine,
             asctime(LocalTime(&crec.start)));

    return 0;
}
示例#16
0
 int main(int argc, char *argv[])
{
  FILE *f;
  pstring fname;
  int uid, c;
  static pstring servicesf = CONFIGFILE;
  extern char *optarg;
  int verbose = 0, brief =0;
  BOOL processes_only=False;
  int last_pid=0;
  struct session_record *ptr;


  TimeInit();
  setup_logging(argv[0],True);

  charset_initialise();

  DEBUGLEVEL = 0;
  dbf = fopen("/dev/null","w");

  if (getuid() != geteuid()) {
    printf("smbstatus should not be run setuid\n");
    return(1);
  }

  while ((c = getopt(argc, argv, "pds:u:b")) != EOF) {
    switch (c) {
    case 'b':
      brief = 1;
      break;
    case 'd':
      verbose = 1;
      break;
    case 'p':
      processes_only = 1;
      break;
    case 's':
      pstrcpy(servicesf, optarg);
      break;
    case 'u':                                       /* added by OH */
      Ucrit_addUsername(optarg);                    /* added by OH */
      break;
    default:
      fprintf(stderr, "Usage: %s [-d] [-p] [-s configfile] [-u username]\n", *argv); /* changed by OH */
      return (-1);
    }
  }

  get_myname(myhostname, NULL);

  if (!lp_load(servicesf,False)) {
    fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
    return (-1);
  }

  if (verbose) {
    printf("using configfile = %s\n", servicesf);
    printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL");
  }

  pstrcpy(fname,lp_lockdir());
  standard_sub_basic(fname);
  trim_string(fname,"","/");
  pstrcat(fname,"/STATUS..LCK");

  f = fopen(fname,"r");
  if (!f) {
    printf("Couldn't open status file %s\n",fname);
    if (!lp_status(-1))
      printf("You need to have status=yes in your smb config file\n");
    return(0);
  }
  else if (verbose) {
    printf("Opened status file %s\n", fname);
  }

  uid = getuid();

  if (!processes_only) {
    printf("\nSamba version %s\n",VERSION);

    if (brief)
    {
      printf("PID     Username  Machine                       Time logged in\n");
      printf("-------------------------------------------------------------------\n");
    }
    else
    {
      printf("Service      uid      gid      pid     machine\n");
      printf("----------------------------------------------\n");
    }
  }

  while (!feof(f))
    {
      if (fread(&crec,sizeof(crec),1,f) != 1)
	break;
      if ( crec.magic == 0x280267 && process_exists(crec.pid) 
           && Ucrit_checkUsername(uidtoname(crec.uid))                      /* added by OH */
         )
      {
        if (brief)
        {
	  ptr=srecs;
	  while (ptr!=NULL)
	  {
	    if ((ptr->pid==crec.pid)&&(strncmp(ptr->machine,crec.machine,30)==0)) 
	    {
	      if (ptr->start > crec.start)
		ptr->start=crec.start;
	      break;
	    }
	    ptr=ptr->next;
	  }
	  if (ptr==NULL)
	  {
	    ptr=(struct session_record *) malloc(sizeof(struct session_record));
	    ptr->uid=crec.uid;
	    ptr->pid=crec.pid;
	    ptr->start=crec.start;
	    strncpy(ptr->machine,crec.machine,30);
	    ptr->machine[30]='\0';
	    ptr->next=srecs;
	    srecs=ptr;
	  }
        }
        else
        {
	  Ucrit_addPid(crec.pid);                                             /* added by OH */
	  if (processes_only) {
	    if (last_pid != crec.pid)
	      printf("%d\n",crec.pid);
	    last_pid = crec.pid; /* XXXX we can still get repeats, have to
				    add a sort at some time */
	  }
	  else	  
	    printf("%-10.10s   %-8s %-8s %5d   %-8s (%s) %s",
		   crec.name,uidtoname(crec.uid),gidtoname(crec.gid),crec.pid,
		   crec.machine,crec.addr,
		   asctime(LocalTime(&crec.start)));
        }
      }
    }
  fclose(f);

  if (processes_only) exit(0);
  
  if (brief)
  {
    ptr=srecs;
    while (ptr!=NULL)
    {
      printf("%-8d%-10.10s%-30.30s%s",ptr->pid,uidtoname(ptr->uid),ptr->machine,asctime(LocalTime(&(ptr->start))));
    ptr=ptr->next;
    }
    printf("\n");
    exit(0);
  }

  printf("\n");

  locking_init(1);

  if (share_mode_forall(print_share_mode) <= 0)
    printf("No locked files\n");

  printf("\n");

  share_status(stdout);

  locking_end();

  return (0);
}
示例#17
0
static int traverse_sessionid(const char *key, struct sessionid *session,
			      void *private_data)
{
	TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
	fstring uid_str, gid_str;
	struct server_id_buf tmp;
	char *machine_hostname = NULL;
	int result = 0;
	const char *encryption = "-";
	const char *signing = "-";

	if (do_checks &&
	    (!process_exists(session->pid) ||
	     !Ucrit_checkUid(session->uid))) {
		return 0;
	}

	Ucrit_addPid(session->pid);

	fstrcpy(uid_str, "-1");

	if (session->uid != -1) {
		if (numeric_only) {
			fstr_sprintf(uid_str, "%u", (unsigned int)session->uid);
		} else {
			fstrcpy(uid_str, uidtoname(session->uid));
		}
	}

	fstrcpy(gid_str, "-1");

	if (session->gid != -1) {
		if (numeric_only) {
			fstr_sprintf(gid_str, "%u", (unsigned int)session->gid);
		} else {
			fstrcpy(gid_str, gidtoname(session->gid));
		}
	}

	machine_hostname = talloc_asprintf(mem_ctx, "%s (%s)",
					   session->remote_machine,
					   session->hostname);
	if (machine_hostname == NULL) {
		return -1;
	}

	if (smbXsrv_is_encrypted(session->encryption_flags)) {
		switch (session->cipher) {
		case SMB2_ENCRYPTION_AES128_CCM:
			encryption = "AES-128-CCM";
			break;
		case SMB2_ENCRYPTION_AES128_GCM:
			encryption = "AES-128-GCM";
			break;
		default:
			encryption = "???";
			result = -1;
			break;
		}
	} else if (smbXsrv_is_partially_encrypted(session->encryption_flags)) {
		switch (session->cipher) {
		case SMB_ENCRYPTION_GSSAPI:
			encryption = "partial(GSSAPI)";
			break;
		case SMB2_ENCRYPTION_AES128_CCM:
			encryption = "partial(AES-128-CCM)";
			break;
		case SMB2_ENCRYPTION_AES128_GCM:
			encryption = "partial(AES-128-GCM)";
			break;
		default:
			encryption = "???";
			result = -1;
			break;
		}
	}

	if (smbXsrv_is_signed(session->signing_flags)) {
		if (session->connection_dialect >= SMB3_DIALECT_REVISION_302) {
			signing = "AES-128-CMAC";
		} else if (session->connection_dialect >= SMB2_DIALECT_REVISION_202) {
			signing = "HMAC-SHA256";
		} else {
			signing = "HMAC-MD5";
		}
	} else if (smbXsrv_is_partially_signed(session->signing_flags)) {
		if (session->connection_dialect >= SMB3_DIALECT_REVISION_302) {
			signing = "partial(AES-128-CMAC)";
		} else if (session->connection_dialect >= SMB2_DIALECT_REVISION_202) {
			signing = "partial(HMAC-SHA256)";
		} else {
			signing = "partial(HMAC-MD5)";
		}
	}


	d_printf("%-7s %-12s %-12s %-41s %-17s %-20s %-21s\n",
		 server_id_str_buf(session->pid, &tmp),
		 uid_str, gid_str,
		 machine_hostname,
		 session_dialect_str(session->connection_dialect),
		 encryption,
		 signing);

	TALLOC_FREE(machine_hostname);

	return result;
}
示例#18
0
int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
                     int argc, const char **argv)
{
    unsigned int ctrl;
    int retval;

    extern BOOL in_client;

    SAM_ACCOUNT *sampass = NULL;
    void (*oldsig_handler)(int);
    const char *user;
    char *pass_old;
    char *pass_new;

    NTSTATUS nt_status;

    /* Samba initialization. */
    setup_logging( "pam_smbpass", False );
    in_client = True;

    ctrl = set_ctrl(flags, argc, argv);

    /*
     * First get the name of a user.  No need to do anything if we can't
     * determine this.
     */

    retval = pam_get_user( pamh, &user, "Username: "******"password: could not identify user" );
        }
        return retval;
    }
    if (on( SMB_DEBUG, ctrl )) {
        _log_err( LOG_DEBUG, "username [%s] obtained", user );
    }

    /* Getting into places that might use LDAP -- protect the app
       from a SIGPIPE it's not expecting */
    oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN);

    if (!initialize_password_db(True)) {
        _log_err( LOG_ALERT, "Cannot access samba password database" );
        CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
        return PAM_AUTHINFO_UNAVAIL;
    }

    /* obtain user record */
    if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
        CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
        return nt_status_to_pam(nt_status);
    }

    if (!pdb_getsampwnam(sampass,user)) {
        _log_err( LOG_ALERT, "Failed to find entry for user %s.", user );
        CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
        return PAM_USER_UNKNOWN;
    }

    if (flags & PAM_PRELIM_CHECK) {
        /*
         * obtain and verify the current password (OLDAUTHTOK) for
         * the user.
         */

        char *Announce;

        if (_smb_blankpasswd( ctrl, sampass )) {

            pdb_free_sam(&sampass);
            CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
            return PAM_SUCCESS;
        }

	/* Password change by root, or for an expired token, doesn't
           require authentication.  Is this a good choice? */
        if (getuid() != 0 && !(flags & PAM_CHANGE_EXPIRED_AUTHTOK)) {

            /* tell user what is happening */
#define greeting "Changing password for "
            Announce = (char *) malloc(sizeof(greeting)+strlen(user));
            if (Announce == NULL) {
                _log_err(LOG_CRIT, "password: out of memory");
                pdb_free_sam(&sampass);
                CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
                return PAM_BUF_ERR;
            }
            strncpy( Announce, greeting, sizeof(greeting) );
            strncpy( Announce+sizeof(greeting)-1, user, strlen(user)+1 );
#undef greeting

            set( SMB__OLD_PASSWD, ctrl );
            retval = _smb_read_password( pamh, ctrl, Announce, "Current SMB password: "******"password - (old) token not obtained" );
                pdb_free_sam(&sampass);
                CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
                return retval;
            }

            /* verify that this is the password for this user */

            retval = _smb_verify_password( pamh, sampass, pass_old, ctrl );

        } else {
	    pass_old = NULL;
            retval = PAM_SUCCESS;           /* root doesn't have to */
        }

        pass_old = NULL;
        pdb_free_sam(&sampass);
        CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
        return retval;

    } else if (flags & PAM_UPDATE_AUTHTOK) {

        /*
         * obtain the proposed password
         */

        /*
         * get the old token back. NULL was ok only if root [at this
         * point we assume that this has already been enforced on a
         * previous call to this function].
         */

        if (off( SMB_NOT_SET_PASS, ctrl )) {
            retval = pam_get_item( pamh, PAM_OLDAUTHTOK,
                                   (const void **)&pass_old );
        } else {
            retval = pam_get_data( pamh, _SMB_OLD_AUTHTOK,
                                   (const void **)&pass_old );
            if (retval == PAM_NO_MODULE_DATA) {
		pass_old = NULL;
                retval = PAM_SUCCESS;
            }
        }

        if (retval != PAM_SUCCESS) {
            _log_err( LOG_NOTICE, "password: user not authenticated" );
            pdb_free_sam(&sampass);
            CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
            return retval;
        }

        /*
         * use_authtok is to force the use of a previously entered
         * password -- needed for pluggable password strength checking
	 * or other module stacking
         */

        if (on( SMB_USE_AUTHTOK, ctrl )) {
            set( SMB_USE_FIRST_PASS, ctrl );
        }

        retval = _smb_read_password( pamh, ctrl
                                      , NULL
                                      , "Enter new SMB password: "******"Retype new SMB password: "******"password: new password not obtained" );
            }
            pass_old = NULL;                               /* tidy up */
            pdb_free_sam(&sampass);
            CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
            return retval;
        }

        /*
         * At this point we know who the user is and what they
         * propose as their new password. Verify that the new
         * password is acceptable.
         */ 

        if (pass_new[0] == '\0') {     /* "\0" password = NULL */
            pass_new = NULL;
        }

        retval = _pam_smb_approve_pass(pamh, ctrl, pass_old, pass_new);

        if (retval != PAM_SUCCESS) {
            _log_err(LOG_NOTICE, "new password not acceptable");
            pass_new = pass_old = NULL;               /* tidy up */
            pdb_free_sam(&sampass);
            CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
            return retval;
        }

        /*
         * By reaching here we have approved the passwords and must now
         * rebuild the smb password file.
         */

        /* update the password database */

        retval = smb_update_db(pamh, ctrl, user, pass_new);
        if (retval == PAM_SUCCESS) {
	    uid_t uid;
	    
            /* password updated */
		if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &uid))) {
			_log_err( LOG_NOTICE, "Unable to get uid for user %s",
				pdb_get_username(sampass));
			_log_err( LOG_NOTICE, "password for (%s) changed by (%s/%d)",
				user, uidtoname(getuid()), getuid());
		} else {
			_log_err( LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)",
				user, uid, uidtoname(getuid()), getuid());
		}
	} else {
		_log_err( LOG_ERR, "password change failed for user %s", user);
	}

        pass_old = pass_new = NULL;
	if (sampass) {
		pdb_free_sam(&sampass);
		sampass = NULL;
	}

    } else {            /* something has broken with the library */

        _log_err( LOG_ALERT, "password received unknown request" );
        retval = PAM_ABORT;

    }
    
    if (sampass) {
    	pdb_free_sam(&sampass);
	sampass = NULL;
    }

    pdb_free_sam(&sampass);
    CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
    return retval;
}