Example #1
0
File: pam_mail.c Project: aosm/pam
static int converse(pam_handle_t *pamh, int ctrl, int nargs
		    , struct pam_message **message
		    , struct pam_response **response)
{
    int retval;
    struct pam_conv *conv;

    D(("begin to converse"));

    retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ; 
    if ( retval == PAM_SUCCESS ) {

	retval = conv->conv(nargs, ( const struct pam_message ** ) message
			    , response, conv->appdata_ptr);

	D(("returned from application's conversation function"));

	if (retval != PAM_SUCCESS && (PAM_DEBUG_ARG & ctrl) ) {
	    _log_err(LOG_DEBUG, "conversation failure [%s]"
		     , pam_strerror(pamh, retval));
	}

    } else {
	_log_err(LOG_ERR, "couldn't obtain coversation function [%s]"
		 , pam_strerror(pamh, retval));
    }

    D(("ready to return from module conversation"));

    return retval;                  /* propagate error status */
}
Example #2
0
PAM_EXTERN int pam_sm_close_session(pam_handle_t * pamh, int flags,
				    int argc, const char **argv)
{
	char *user_name, *service;
	unsigned int ctrl;
	int retval;

	D(("called."));

	ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);

	retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
	if (user_name == NULL || retval != PAM_SUCCESS) {
		_log_err(LOG_CRIT, pamh,
		         "close_session - error recovering username");
		return PAM_SESSION_ERR;		/* How did we get authenticated with
						   no username?! */
	}
	retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service);
	if (service == NULL || retval != PAM_SUCCESS) {
		_log_err(LOG_CRIT, pamh,
		         "close_session - error recovering service");
		return PAM_SESSION_ERR;
	}
	_log_err(LOG_INFO, pamh, "session closed for user %s"
		 ,user_name);

	return PAM_SUCCESS;
}
Example #3
0
static int parse_args(struct login_info *loginfo, int argc, const char **argv)
{
    int i;

    for (i=0; i<argc; ++i) {
	if (!strncmp("fieldsep=", argv[i], 9)) {

	    /* the admin wants to override the default field separators */
	    fs = argv[i]+9;

	} else if (!strncmp("accessfile=", argv[i], 11)) {
	    FILE *fp = fopen(11 + argv[i], "r");

	    if (fp) {
		loginfo->config_file = 11 + argv[i];
		fclose(fp);
	    } else {
		_log_err("for service [%s] failed to open accessfile=[%s]"
			 , loginfo->service, 11 + argv[i]);
		return 0;
	    }
	    
	} else {
	    _log_err("unrecognized option [%s]", argv[i]);
	}
    }
    
    return 1;  /* OK */
}
static char *getNISserver(pam_handle_t *pamh)
{
	char *master;
	char *domainname;
	int port, err;

	if ((err = yp_get_default_domain(&domainname)) != 0) {
		_log_err(LOG_WARNING, pamh, "can't get local yp domain: %s\n",
			 yperr_string(err));
		return NULL;
	}
	if ((err = yp_master(domainname, "passwd.byname", &master)) != 0) {
		_log_err(LOG_WARNING, pamh, "can't find the master ypserver: %s\n",
			 yperr_string(err));
		return NULL;
	}
	port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP);
	if (port == 0) {
		_log_err(LOG_WARNING, pamh,
		         "yppasswdd not running on NIS master host\n");
		return NULL;
	}
	if (port >= IPPORT_RESERVED) {
		_log_err(LOG_WARNING, pamh,
		         "yppasswd daemon running on illegal port.\n");
		return NULL;
	}
	return master;
}
Example #5
0
static _ctx *
_profile_thread(PyThreadState *ts)
{
    uintptr_t ctx_id;
    _ctx *ctx;
    _hitem *it;

    ctx_id = _current_context_id(ts);
    it = hfind(contexts, ctx_id);
    if (!it) {
        ctx = _create_ctx();
        if (!ctx) {
            return NULL;
        }    
        if (!hadd(contexts, ctx_id, (uintptr_t)ctx)) {
            _del_ctx(ctx);
            if (!flput(flctx, ctx)) {
                _log_err(10);
            }
            _log_err(11);
            return NULL;
        }
    } else {
        ctx = (_ctx *)it->val;
    }
    
    ts->use_tracing = 1;
    ts->c_profilefunc = _yapp_callback;
    ctx->id = ctx_id;
    ctx->tid = ts->thread_id;

    return ctx;
}
Example #6
0
File: pam_mail.c Project: aosm/pam
static int _pam_parse(int flags, int argc, const char **argv, char **maildir,
		      int *hashcount)
{
    int ctrl=0;

    if (flags & PAM_SILENT) {
	ctrl |= PAM_MAIL_SILENT;
    }

    *hashcount = 0;

    /* step through arguments */
    for (; argc-- > 0; ++argv) {

	/* generic options */

	if (!strcmp(*argv,"debug"))
	    ctrl |= PAM_DEBUG_ARG;
	else if (!strcmp(*argv,"quiet"))
	    ctrl |= PAM_QUIET_MAIL;
	else if (!strcmp(*argv,"standard"))
	    ctrl |= PAM_STANDARD_MAIL | PAM_EMPTY_TOO;
	else if (!strncmp(*argv,"dir=",4)) {
	    *maildir = x_strdup(4+*argv);
	    if (*maildir != NULL) {
		D(("new mail directory: %s", *maildir));
		ctrl |= PAM_NEW_MAIL_DIR;
	    } else {
		_log_err(LOG_CRIT,
			 "failed to duplicate mail directory - ignored");
	    }
	} else if (!strncmp(*argv,"hash=",5)) {
	    char *ep = NULL;
	    *hashcount = strtol(*argv+5,&ep,10);
	    if (!ep || (*hashcount < 0)) {
		*hashcount = 0;
	    }
	} else if (!strcmp(*argv,"close")) {
	    ctrl |= PAM_LOGOUT_TOO;
	} else if (!strcmp(*argv,"nopen")) {
	    ctrl |= PAM_NO_LOGIN;
	} else if (!strcmp(*argv,"noenv")) {
	    ctrl |= PAM_NO_ENV;
	} else if (!strcmp(*argv,"empty")) {
	    ctrl |= PAM_EMPTY_TOO;
	} else {
	    _log_err(LOG_ERR,"pam_parse: unknown option; %s",*argv);
	}
    }

    if ((*hashcount != 0) && !(ctrl & PAM_NEW_MAIL_DIR)) {
	*maildir = x_strdup(DEFAULT_MAIL_DIRECTORY);
	ctrl |= PAM_NEW_MAIL_DIR;
    }

    return ctrl;
}
Example #7
0
static int login_access(struct login_info *item)
{
    FILE   *fp;
    char    line[BUFSIZ];
    char   *perm;		/* becomes permission field */
    char   *users;		/* becomes list of login names */
    char   *froms;		/* becomes list of terminals or hosts */
    int     match = NO;
    int     end;
    int     lineno = 0;		/* for diagnostics */

    /*
     * Process the table one line at a time and stop at the first match.
     * Blank lines and lines that begin with a '#' character are ignored.
     * Non-comment lines are broken at the ':' character. All fields are
     * mandatory. The first field should be a "+" or "-" character. A
     * non-existing table means no access control.
     */

    if ((fp = fopen(item->config_file, "r"))!=NULL) {
	while (!match && fgets(line, sizeof(line), fp)) {
	    lineno++;
	    if (line[end = strlen(line) - 1] != '\n') {
		_log_err("%s: line %d: missing newline or line too long",
		       item->config_file, lineno);
		continue;
	    }
	    if (line[0] == '#')
		continue;			/* comment line */
	    while (end > 0 && isspace(line[end - 1]))
		end--;
	    line[end] = 0;			/* strip trailing whitespace */
	    if (line[0] == 0)			/* skip blank lines */
		continue;
	    if (!(perm = strtok(line, fs))
		|| !(users = strtok((char *) 0, fs))
		|| !(froms = strtok((char *) 0, fs))
		|| strtok((char *) 0, fs)) {
		_log_err("%s: line %d: bad field count",
			 item->config_file, lineno);
		continue;
	    }
	    if (perm[0] != '+' && perm[0] != '-') {
		_log_err("%s: line %d: bad first field",
			 item->config_file, lineno);
		continue;
	    }
	    match = (list_match(froms, item, from_match)
		     && list_match(users, item, user_match));
	}
	(void) fclose(fp);
    } else if (errno != ENOENT) {
	_log_err("cannot open %s: %m", item->config_file);
    }
    return (match == 0 || (line[0] == '+'));
}
static int _pam_unix_approve_pass(pam_handle_t * pamh
				  ,unsigned int ctrl
				  ,const char *pass_old
				  ,const char *pass_new)
{
	const char *user;
	const char *remark = NULL;
	int retval = PAM_SUCCESS;

	D(("&new=%p, &old=%p", pass_old, pass_new));
	D(("new=[%s]", pass_new));
	D(("old=[%s]", pass_old));

	if (pass_new == NULL || (pass_old && !strcmp(pass_old, pass_new))) {
		if (on(UNIX_DEBUG, ctrl)) {
			_log_err(LOG_DEBUG, pamh, "bad authentication token");
		}
		_make_remark(pamh, ctrl, PAM_ERROR_MSG, pass_new == NULL ?
			  "No password supplied" : "Password unchanged");
		return PAM_AUTHTOK_ERR;
	}
	/*
	 * if one wanted to hardwire authentication token strength
	 * checking this would be the place - AGM
	 */

	retval = pam_get_item(pamh, PAM_USER, (const void **) &user);
	if (retval != PAM_SUCCESS) {
		if (on(UNIX_DEBUG, ctrl)) {
			_log_err(LOG_ERR, pamh, "Can not get username");
			return PAM_AUTHTOK_ERR;
		}
	}
	if (off(UNIX__IAMROOT, ctrl)) {
#ifdef USE_CRACKLIB
		remark = FascistCheck(pass_new, CRACKLIB_DICTS);
		D(("called cracklib [%s]", remark));
#else
		if (strlen(pass_new) < 6)
			remark = "You must choose a longer password";
		D(("lenth check [%s]", remark));
#endif
		if (on(UNIX_REMEMBER_PASSWD, ctrl))
			if ((retval = check_old_password(user, pass_new)) != PAM_SUCCESS)
				remark = "Password has been already used. Choose another.";
	}
	if (remark) {
		_make_remark(pamh, ctrl, PAM_ERROR_MSG, remark);
		retval = PAM_AUTHTOK_ERR;
	}
	return retval;
}
Example #9
0
File: pam_time.c Project: aosm/pam
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
		     ,const char **argv)
{
    const char *service=NULL, *tty=NULL;
    const char *user=NULL;

    /* set service name */

    if (pam_get_item(pamh, PAM_SERVICE, (const void **)&service)
	!= PAM_SUCCESS || service == NULL) {
	_log_err("cannot find the current service name");
	return PAM_ABORT;
    }

    /* set username */

    if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL
	|| *user == '\0') {
	_log_err("cannot determine the user's name");
	return PAM_USER_UNKNOWN;
    }

    /* set tty name */

    if (pam_get_item(pamh, PAM_TTY, (const void **)&tty) != PAM_SUCCESS
	|| tty == NULL) {
	D(("PAM_TTY not set, probing stdin"));
	tty = ttyname(STDIN_FILENO);
	if (tty == NULL) {
	    _log_err("couldn't get the tty name");
	    return PAM_ABORT;
	}
	if (pam_set_item(pamh, PAM_TTY, tty) != PAM_SUCCESS) {
	    _log_err("couldn't set tty name");
	    return PAM_ABORT;
	}
    }

    if (strncmp("/dev/",tty,5) == 0) {          /* strip leading /dev/ */
	tty += 5;
    }

    /* good, now we have the service name, the user and the terminal name */

    D(("service=%s", service));
    D(("user=%s", user));
    D(("tty=%s", tty));

    return check_account(service,tty,user);
}
Example #10
0
static void su_sighandler(int sig)
{
	if (sig > 0) {
		_log_err(LOG_NOTICE, "caught signal %d.", sig);
		exit(sig);
	}
}
static int _pam_parse(int flags, int argc, const char **argv)
{
   int ctrl = 0;

   /* does the appliction require quiet? */
   if ((flags & PAM_SILENT) == PAM_SILENT)
      ctrl |= MKHOMEDIR_QUIET;

   /* step through arguments */
   for (; argc-- > 0; ++argv)
   {
      if (!strcmp(*argv, "silent")) {
	 ctrl |= MKHOMEDIR_QUIET;
      } else if (!strncmp(*argv,"umask=",6)) {
	 UMask = strtol(*argv+6,0,0);
      } else if (!strncmp(*argv,"skel=",5)) {
	 strncpy(SkelDir,*argv+5,sizeof(SkelDir));
	 SkelDir[sizeof(SkelDir)-1] = '\0';
      } else {
	 _log_err(LOG_ERR, "unknown option; %s", *argv);
      }
   }

   D(("ctrl = %o", ctrl));
   return ctrl;
}
PAM_EXTERN
int pam_sm_open_session(pam_handle_t * pamh, int flags, int argc
			,const char **argv)
{
   int retval, ctrl;
   const char *user;
   const struct passwd *pwd;
   struct stat St;
      
   /* Parse the flag values */
   ctrl = _pam_parse(flags, argc, argv);

   /* Determine the user name so we can get the home directory */
   retval = pam_get_item(pamh, PAM_USER, (const void **) &user);
   if (retval != PAM_SUCCESS || user == NULL || *user == '\0')
   {
      _log_err(LOG_NOTICE, "user unknown");
      return PAM_USER_UNKNOWN;
   }

   /* Get the password entry */
   pwd = getpwnam(user);
   if (pwd == NULL)
   {
      D(("couldn't identify user %s", user));
      return PAM_CRED_INSUFFICIENT;
   }

   /* Stat the home directory, if something exists then we assume it is
      correct and return a success*/
   if (stat(pwd->pw_dir,&St) == 0)
      return PAM_SUCCESS;

   return create_homedir(pamh,ctrl,pwd,SkelDir,pwd->pw_dir);
}
Example #13
0
File: pam_time.c Project: aosm/pam
static boolean logic_field(const void *me, const char *x, int rule,
			   boolean (*agrees)(const void *, const char *
					     , int, int))
{
     boolean left=FALSE, right, not=FALSE;
     operator oper=OR;
     int at=0, l;
     expect next=VAL;

     while ((l = logic_member(x,&at))) {
	  int c = x[at];

	  if (next == VAL) {
	       if (c == '!')
		    not = !not;
	       else if (isalpha(c) || c == '*') {
		    right = not ^ agrees(me, x+at, l, rule);
		    if (oper == AND)
			 left &= right;
		    else
			 left |= right;
		    next = OP;
	       } else {
		    _log_err("garbled syntax; expected name (rule #%d)", rule);
		    return FALSE;
	       }
	  } else {   /* OP */
	       switch (c) {
	       case '&':
		    oper = AND;
		    break;
	       case '|':
		    oper = OR;
		    break;
	       default:
		    _log_err("garbled syntax; expected & or | (rule #%d)"
			     , rule);
		    D(("%c at %d",c,at));
		    return FALSE;
	       }
	       next = VAL;
	  }
	  at += l;
     }

     return left;
}
Example #14
0
static void
_call_enter(PyObject *self, PyFrameObject *frame, PyObject *arg, int ccall)
{
    _pit *cp,*pp;
    _cstackitem *ci;
    _pit_children_info *pci;

    if (ccall) {
        cp = _ccode2pit((PyCFunctionObject *)arg);
    } else {
        cp = _code2pit(frame);
    }

    // something went wrong. No mem, or another error. we cannot find
    // a corresponding pit. just run away:)
    if (!cp) {
        _log_err(4);
        return;
    }

    // create/update children info if we have a valid parent
    pp = _get_frame();
    if (pp) {
        pci = _get_child_info(pp, cp);
        if(!pci)
        {
            pci = _add_child_info(pp, cp);
        }
        pci->callcount++;
        incr_rec_level((uintptr_t)pci);
    }

    ci = _push_frame(cp);
    if (!ci) { // runaway! (defensive)
        _log_err(5);
        return;
    }

    ci->t0 = tickcount();
    cp->callcount++;
    incr_rec_level((uintptr_t)cp);
}
Example #15
0
/* Helper function for adding a user to the db. */
static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl,
                         const char *name, struct samu *sampass, bool exist)
{
	char *err_str = NULL;
	char *msg_str = NULL;
	const char *pass = NULL;
	int retval;
	TALLOC_CTX *frame = talloc_stackframe();

	/* Get the authtok; if we don't have one, silently fail. */
	retval = _pam_get_item( pamh, PAM_AUTHTOK, &pass );

	if (retval != PAM_SUCCESS) {
		_log_err(pamh, LOG_ALERT
			, "pam_get_item returned error to pam_sm_authenticate" );
		TALLOC_FREE(frame);
		return PAM_AUTHTOK_RECOVER_ERR;
	}

	/* Add the user to the db if they aren't already there. */
	if (!exist) {
		retval = NT_STATUS_IS_OK(local_password_change(name, LOCAL_ADD_USER|LOCAL_SET_PASSWORD,
					pass, &err_str, &msg_str));
		if (!retval && err_str) {
			make_remark(pamh, ctrl, PAM_ERROR_MSG, err_str );
		} else if (msg_str) {
			make_remark(pamh, ctrl, PAM_TEXT_INFO, msg_str );
		}
		pass = NULL;

		SAFE_FREE(err_str);
		SAFE_FREE(msg_str);
		TALLOC_FREE(frame);
		return PAM_IGNORE;
	} else {
		/* mimick 'update encrypted' as long as the 'no pw req' flag is not set */
		if ( pdb_get_acct_ctrl(sampass) & ~ACB_PWNOTREQ ) {
			retval = NT_STATUS_IS_OK(local_password_change(name, LOCAL_SET_PASSWORD,
					pass, &err_str, &msg_str));
			if (!retval && err_str) {
				make_remark(pamh, ctrl, PAM_ERROR_MSG, err_str );
			} else if (msg_str) {
				make_remark(pamh, ctrl, PAM_TEXT_INFO, msg_str );
			}
		}
	}
    
	SAFE_FREE(err_str);
	SAFE_FREE(msg_str);
	pass = NULL;
	TALLOC_FREE(frame);
	return PAM_IGNORE;
}
Example #16
0
static long
get_rec_level(uintptr_t key)
{
    _hitem *it;

    it = hfind(current_ctx->rec_levels, key);
    if (!it) {
        _log_err(1);
        return -1; // should not happen
    }
    return it->val;
}
Example #17
0
static int
_authenticate(const char *service, const char *user)
{
	struct pam_conv conv = { _converse, NULL };
	pam_handle_t	*pamh;
	int		err;

	err = pam_start(service, user, &conv, &pamh);
	if (err != PAM_SUCCESS) {
		_log_err(LOG_ERR, "pam_start(%s, %s) failed (errno %d)",
				service, user, err);
		return UNIX_FAILED;
	}

	err = pam_authenticate(pamh, 0);
	if (err != PAM_SUCCESS)
		_log_err(LOG_ERR, "pam_authenticate(%s, %s): %s",
				service, user,
				pam_strerror(pamh, err));

	if (err == PAM_SUCCESS)
	{
		int err2 = pam_setcred(pamh, PAM_REFRESH_CRED);
		if (err2 != PAM_SUCCESS)
			_log_err(LOG_ERR, "pam_setcred(%s, %s): %s",
					 service, user,
					 pam_strerror(pamh, err2));
		/*
		 * ignore errors on refresh credentials.
		 * If this did not work we use the old once.
		 */
	}

	pam_end(pamh, err);

	if (err != PAM_SUCCESS)
		return UNIX_FAILED;
	return UNIX_PASSED;
}
Example #18
0
static int netgroup_match(char *group, char *machine, char *user)
{
#ifdef NIS
    static char *mydomain = 0;

    if (mydomain == 0)
	yp_get_default_domain(&mydomain);
    return (innetgr(group, machine, user, mydomain));
#else
    _log_err("NIS netgroup support not configured");
    return (NO);
#endif
}
Example #19
0
static int
incr_rec_level(uintptr_t key)
{
    _hitem *it;

    it = hfind(current_ctx->rec_levels, key);
    if (it) {
        it->val++;
    } else {
        if (!hadd(current_ctx->rec_levels, key, 1))
        {
            _log_err(2);
            return 0; // should not happen
        }
    }
    return 1;
}
Example #20
0
static int
decr_rec_level(uintptr_t key)
{
    _hitem *it;
    uintptr_t v;

    it = hfind(current_ctx->rec_levels, key);
    if (it) {
        v = it->val--;  /*supress warning -- it is safe to cast long vs pointers*/
        if (v == 0)
        {
            hfree(current_ctx->rec_levels, it);
        }
    } else {
        _log_err(3);
        return 0; // should not happen
    }
    return 1;
}
Example #21
0
static int
_converse(int num_msg, const struct pam_message **msg,
		struct pam_response **resp, void *appdata_ptr)
{
	struct	pam_response *reply;
	int	num;

	if (!(reply = malloc(sizeof(*reply) * num_msg)))
		return PAM_CONV_ERR;

	for (num = 0; num < num_msg; num++) {
		reply[num].resp_retcode = PAM_SUCCESS;
		reply[num].resp = NULL;
		switch (msg[num]->msg_style) {
		case PAM_PROMPT_ECHO_ON:
			return PAM_CONV_ERR;
		case PAM_PROMPT_ECHO_OFF:
			/* read the password from stdin */
			if (npass < 0) {
				npass = read(STDIN_FILENO, pass, sizeof(pass)-1);
				if (npass < 0) {
					_log_err(LOG_DEBUG, "error reading password");
					return UNIX_FAILED;
				}
				pass[npass] = '\0';
			}
			reply[num].resp = strdup(pass);
			break;
		case PAM_TEXT_INFO:
		case PAM_ERROR_MSG:
			/* ignored */
			break;
		default:
			/* Must be an error of some sort... */
			return PAM_CONV_ERR;
		}
	}

	*resp = reply;
	return PAM_SUCCESS;
}
Example #22
0
File: pam_mail.c Project: aosm/pam
static int _do_mail(pam_handle_t *pamh, int flags, int argc,
    const char **argv, int est)
{
    int retval, ctrl, hashcount;
    char *path_mail=NULL, *folder;
    const char *type;

    /*
     * this module (un)sets the MAIL environment variable, and checks if
     * the user has any new mail.
     */

    ctrl = _pam_parse(flags, argc, argv, &path_mail, &hashcount);

    /* Do we have anything to do? */

    if (flags & PAM_SILENT)
	return PAM_SUCCESS;

    /* which folder? */

    retval = get_folder(pamh, ctrl, &path_mail, &folder, hashcount);
    if (retval != PAM_SUCCESS) {
	D(("failed to find folder"));
	return retval;
    }

    /* set the MAIL variable? */

    if (!(ctrl & PAM_NO_ENV) && est) {
	char *tmp;

	tmp = malloc(strlen(folder)+sizeof(MAIL_ENV_FORMAT));
	if (tmp != NULL) {
	    sprintf(tmp, MAIL_ENV_FORMAT, folder);
	    D(("setting env: %s", tmp));
	    retval = pam_putenv(pamh, tmp);
	    _pam_overwrite(tmp);
	    _pam_drop(tmp);
	    if (retval != PAM_SUCCESS) {
		_pam_overwrite(folder);
		_pam_drop(folder);
		_log_err(LOG_CRIT, "unable to set " MAIL_ENV_NAME " variable");
		return retval;
	    }
	} else {
	    _log_err(LOG_CRIT, "no memory for " MAIL_ENV_NAME " variable");
	    _pam_overwrite(folder);
	    _pam_drop(folder);
	    return retval;
	}
    } else {
	D(("not setting " MAIL_ENV_NAME " variable"));
    }

    /*
     * OK. we've got the mail folder... what about its status?
     */

    if ((est && !(ctrl & PAM_NO_LOGIN))
	|| (!est && (ctrl & PAM_LOGOUT_TOO))) {
	type = get_mail_status(ctrl, folder);
	if (type != NULL) {
	    retval = report_mail(pamh, ctrl, type, folder);
	    type = NULL;
	}
    }
    
    /* Delete environment variable? */  
    if (!est)
	(void) pam_putenv(pamh, MAIL_ENV_NAME);

    _pam_overwrite(folder); /* clean up */
    _pam_drop(folder);

    /* indicate success or failure */

    return retval;
}
Example #23
0
File: pam_mail.c Project: aosm/pam
static int get_folder(pam_handle_t *pamh, int ctrl,
		      char **path_mail, char **folder_p, int hashcount)
{
    int retval;
    const char *user, *path;
    char *folder;
    const struct passwd *pwd=NULL;

    retval = pam_get_user(pamh, &user, NULL);
    if (retval != PAM_SUCCESS || user == NULL) {
	_log_err(LOG_ERR, "no user specified");
	return PAM_USER_UNKNOWN;
    }

    if (ctrl & PAM_NEW_MAIL_DIR) {
	path = *path_mail;
	if (*path == '~') {       /* support for $HOME delivery */
	    pwd = getpwnam(user);
	    if (pwd == NULL) {
		_log_err(LOG_ERR, "user [%s] unknown", user);
		_pam_overwrite(*path_mail);
		_pam_drop(*path_mail);
		return PAM_USER_UNKNOWN;
	    }
	    /*
	     * "~/xxx" and "~xxx" are treated as same
	     */
	    if (!*++path || (*path == '/' && !*++path)) {
		_log_err(LOG_ALERT, "badly formed mail path [%s]", *path_mail);
		_pam_overwrite(*path_mail);
		_pam_drop(*path_mail);
		return PAM_ABORT;
	    }
	    ctrl |= PAM_HOME_MAIL;
	    if (hashcount != 0) {
		_log_err(LOG_ALERT, "can't do hash= and home directory mail");
	    }
	}
    } else {
	path = DEFAULT_MAIL_DIRECTORY;
    }

    /* put folder together */

    if (ctrl & PAM_HOME_MAIL) {
	folder = malloc(sizeof(MAIL_FILE_FORMAT)
			+strlen(pwd->pw_dir)+strlen(path));
    } else {
	folder = malloc(sizeof(MAIL_FILE_FORMAT)+strlen(path)+strlen(user)
			+2*hashcount);
    }

    if (folder != NULL) {
	if (ctrl & PAM_HOME_MAIL) {
	    sprintf(folder, MAIL_FILE_FORMAT, pwd->pw_dir, "", path);
	} else {
	    int i;
	    char *hash = malloc(2*hashcount+1);

	    if (hash) {
		for (i = 0; i < hashcount; i++) {
		    hash[2*i] = '/';
		    hash[2*i+1] = user[i];
		}
		hash[2*i] = '\0';
		sprintf(folder, MAIL_FILE_FORMAT, path, hash, user);
		_pam_overwrite(hash);
		_pam_drop(hash);
	    } else {
		sprintf(folder, "error");
	    }
	}
	D(("folder =[%s]", folder));
    }

    /* tidy up */

    _pam_overwrite(*path_mail);
    _pam_drop(*path_mail);
    user = NULL;

    if (folder == NULL) {
	_log_err(LOG_CRIT, "out of memory for mail folder");
	return PAM_BUF_ERR;
    }

    *folder_p = folder;
    folder = NULL;

    return PAM_SUCCESS;
}
Example #24
0
File: pam_time.c Project: aosm/pam
static int read_field(int fd, char **buf, int *from, int *to)
{
    /* is buf set ? */

    if (! *buf) {
	*buf = (char *) malloc(PAM_TIME_BUFLEN);
	if (! *buf) {
	    _log_err("out of memory");
	    D(("no memory"));
	    return -1;
	}
	*from = *to = 0;
	fd = open(PAM_TIME_CONF, O_RDONLY);
    }

    /* do we have a file open ? return error */

    if (fd < 0 && *to <= 0) {
	_log_err( PAM_TIME_CONF " not opened");
	memset(*buf, 0, PAM_TIME_BUFLEN);
	_pam_drop(*buf);
	return -1;
    }

    /* check if there was a newline last time */

    if ((*to > *from) && (*to > 0)
	&& ((*buf)[*from] == '\0')) { /* previous line ended */
	(*from)++;
	(*buf)[0] = '\0';
	return fd;
    }

    /* ready for more data: first shift the buffer's remaining data */

    *to -= *from;
    shift_bytes(*buf, *from, *to);
    *from = 0;
    (*buf)[*to] = '\0';

    while (fd >= 0 && *to < PAM_TIME_BUFLEN) {
	int i;

	/* now try to fill the remainder of the buffer */

	i = read(fd, *to + *buf, PAM_TIME_BUFLEN - *to);
	if (i < 0) {
	    _log_err("error reading " PAM_TIME_CONF);
	    return -1;
	} else if (!i) {
	    close(fd);
	    fd = -1;          /* end of file reached */
	} else
	    *to += i;
    
	/*
	 * contract the buffer. Delete any comments, and replace all
	 * multiple spaces with single commas
	 */

	i = 0;
#ifdef DEBUG_DUMP
	D(("buffer=<%s>",*buf));
#endif
	while (i < *to) {
	    if ((*buf)[i] == ',') {
		int j;

		for (j=++i; j<*to && (*buf)[j] == ','; ++j);
		if (j!=i) {
		    shift_bytes(i + (*buf), j-i, (*to) - j);
		    *to -= j-i;
		}
	    }
	    switch ((*buf)[i]) {
		int j,c;
	    case '#':
		for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
		if (j >= *to) {
		    (*buf)[*to = ++i] = '\0';
		} else if (c == '\n') {
		    shift_bytes(i + (*buf), j-i, (*to) - j);
		    *to -= j-i;
		    ++i;
		} else {
		    _log_err("internal error in " __FILE__
			     " at line %d", __LINE__ );
		    return -1;
		}
		break;
	    case '\\':
		if ((*buf)[i+1] == '\n') {
		    shift_bytes(i + *buf, 2, *to - (i+2));
		    *to -= 2;
		} else {
		    ++i;   /* we don't escape non-newline characters */
		}
		break;
	    case '!':
	    case ' ':
	    case '\t':
		if ((*buf)[i] != '!')
		    (*buf)[i] = ',';
		/* delete any trailing spaces */
		for (j=++i; j < *to && ( (c = (*buf)[j]) == ' '
					 || c == '\t' ); ++j);
		shift_bytes(i + *buf, j-i, (*to)-j );
		*to -= j-i;
		break;
	    default:
		++i;
	    }
	}
    }

    (*buf)[*to] = '\0';

    /* now return the next field (set the from/to markers) */
    {
	int i;

	for (i=0; i<*to; ++i) {
	    switch ((*buf)[i]) {
	    case '#':
	    case '\n':               /* end of the line/file */
		(*buf)[i] = '\0';
		*from = i;
		return fd;
	    case FIELD_SEPARATOR:    /* end of the field */
		(*buf)[i] = '\0';
	    *from = ++i;
	    return fd;
	    }
	}
	*from = i;
	(*buf)[*from] = '\0';
    }

    if (*to <= 0) {
	D(("[end of text]"));
	*buf = NULL;
    }

    return fd;
}
Example #25
0
File: pam_time.c Project: aosm/pam
static int check_account(const char *service
			 , const char *tty, const char *user)
{
     int from=0,to=0,fd=-1;
     char *buffer=NULL;
     int count=0;
     TIME here_and_now;
     int retval=PAM_SUCCESS;

     here_and_now = time_now();                     /* find current time */
     do {
	  boolean good=TRUE,intime;

	  /* here we get the service name field */

	  fd = read_field(fd,&buffer,&from,&to);

	  if (!buffer || !buffer[0]) {
	       /* empty line .. ? */
	       continue;
	  }
	  ++count;

	  good = logic_field(service, buffer, count, is_same);
	  D(("with service: %s", good ? "passes":"fails" ));

	  /* here we get the terminal name field */

	  fd = read_field(fd,&buffer,&from,&to);
	  if (!buffer || !buffer[0]) {
	       _log_err(PAM_TIME_CONF "; no tty entry #%d", count);
	       continue;
	  }
	  good &= logic_field(tty, buffer, count, is_same);
	  D(("with tty: %s", good ? "passes":"fails" ));

	  /* here we get the username field */

	  fd = read_field(fd,&buffer,&from,&to);
	  if (!buffer || !buffer[0]) {
	       _log_err(PAM_TIME_CONF "; no user entry #%d", count);
	       continue;
	  }
	  good &= logic_field(user, buffer, count, is_same);
	  D(("with user: %s", good ? "passes":"fails" ));

	  /* here we get the time field */

	  fd = read_field(fd,&buffer,&from,&to);
	  if (!buffer || !buffer[0]) {
	       _log_err(PAM_TIME_CONF "; no time entry #%d", count);
	       continue;
	  }

	  intime = logic_field(&here_and_now, buffer, count, check_time);
	  D(("with time: %s", intime ? "passes":"fails" ));

	  fd = read_field(fd,&buffer,&from,&to);
	  if (buffer && buffer[0]) {
	       _log_err(PAM_TIME_CONF "; poorly terminated rule #%d", count);
	       continue;
	  }

	  if (good && !intime) {
	       /*
		* for security parse whole file..  also need to ensure
		* that the buffer is free()'d and the file is closed.
		*/
	       retval = PAM_PERM_DENIED;
	  } else {
	       D(("rule passed"));
	  }
     } while (buffer);

     return retval;
}
Example #26
0
File: pam_time.c Project: aosm/pam
/* take the current date and see if the range "date" passes it */
static boolean check_time(const void *AT, const char *times, int len, int rule)
{
     boolean not,pass;
     int marked_day, time_start, time_end;
     const TIME *at;
     int i,j=0;

     at = AT;
     D(("chcking: 0%o/%.4d vs. %s", at->day, at->minute, times));

     if (times == NULL) {
	  /* this should not happen */
	  _log_err("internal error: " __FILE__ " line %d", __LINE__);
	  return FALSE;
     }

     if (times[j] == '!') {
	  ++j;
	  not = TRUE;
     } else {
	  not = FALSE;
     }

     for (marked_day = 0; len > 0 && isalpha(times[j]); --len) {
	  int this_day=-1;

	  D(("%c%c ?", times[j], times[j+1]));
	  for (i=0; days[i].d != NULL; ++i) {
	       if (tolower(times[j]) == days[i].d[0]
		   && tolower(times[j+1]) == days[i].d[1] ) {
		    this_day = days[i].bit;
		    break;
	       }
	  }
	  j += 2;
	  if (this_day == -1) {
	       _log_err("bad day specified (rule #%d)", rule);
	       return FALSE;
	  }
	  marked_day ^= this_day;
     }
     if (marked_day == 0) {
	  _log_err("no day specified");
	  return FALSE;
     }
     D(("day range = 0%o", marked_day));

     time_start = 0;
     for (i=0; len > 0 && i < 4 && isdigit(times[i+j]); ++i, --len) {
	  time_start *= 10;
	  time_start += times[i+j]-'0';        /* is this portable? */
     }
     j += i;

     if (times[j] == '-') {
	  time_end = 0;
	  for (i=1; len > 0 && i < 5 && isdigit(times[i+j]); ++i, --len) {
	       time_end *= 10;
	       time_end += times[i+j]-'0';    /* is this portable */
	  }
	  j += i;
     } else
	  time_end = -1;

     D(("i=%d, time_end=%d, times[j]='%c'", i, time_end, times[j]));
     if (i != 5 || time_end == -1) {
	  _log_err("no/bad times specified (rule #%d)", rule);
	  return TRUE;
     }
     D(("times(%d to %d)", time_start,time_end));
     D(("marked_day = 0%o", marked_day));

     /* compare with the actual time now */

     pass = FALSE;
     if (time_start < time_end) {    /* start < end ? --> same day */
	  if ((at->day & marked_day) && (at->minute >= time_start)
	      && (at->minute < time_end)) {
	       D(("time is listed"));
	       pass = TRUE;
	  }
     } else {                                    /* spans two days */
	  if ((at->day & marked_day) && (at->minute >= time_start)) {
	       D(("caught on first day"));
	       pass = TRUE;
	  } else {
	       marked_day <<= 1;
	       marked_day |= (marked_day & 0200) ? 1:0;
	       D(("next day = 0%o", marked_day));
	       if ((at->day & marked_day) && (at->minute <= time_end)) {
		    D(("caught on second day"));
		    pass = TRUE;
	       }
	  }
     }

     return (not ^ pass);
}
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
				int argc, const char **argv)
{
	unsigned int ctrl, lctrl;
	int retval, i;
	int remember = -1;

	/* <DO NOT free() THESE> */
	const char *user;
	char *pass_old, *pass_new;
	/* </DO NOT free() THESE> */

	D(("called."));

#ifdef USE_LCKPWDF
	/* our current locking system requires that we lock the
	   entire password database.  This avoids both livelock
	   and deadlock. */
	/* These values for the number of attempts and the sleep time
	   are, of course, completely arbitrary.
	   My reading of the PAM docs is that, once pam_chauthtok() has been
	   called with PAM_UPDATE_AUTHTOK, we are obliged to take any
	   reasonable steps to make sure the token is updated; so retrying
	   for 1/10 sec. isn't overdoing it.
	   The other possibility is to call lckpwdf() on the first
	   pam_chauthtok() pass, and hold the lock until released in the
	   second pass--but is this guaranteed to work? -SRL */
	i=0;
	while((retval = lckpwdf()) != 0 && i < 100) {
		usleep(1000);
	}
	if(retval != 0) {
		return PAM_AUTHTOK_LOCK_BUSY;
	}
#endif
	ctrl = _set_ctrl(pamh, flags, &remember, argc, argv);

	/*
	 * First get the name of a user
	 */
	retval = pam_get_user(pamh, &user, "Username: "******"bad username [%s]", user);
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return PAM_USER_UNKNOWN;
		}
		if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
			_log_err(LOG_DEBUG, pamh, "username [%s] obtained",
			         user);
	} else {
		if (on(UNIX_DEBUG, ctrl))
			_log_err(LOG_DEBUG, pamh,
			         "password - could not identify user");
#ifdef USE_LCKPWDF
		ulckpwdf();
#endif
		return retval;
	}

	D(("Got username of %s", user));

	/*
	 * This is not an AUTH module!
	 */
	if (on(UNIX__NONULL, ctrl))
		set(UNIX__NULLOK, ctrl);

	if (on(UNIX__PRELIM, ctrl)) {
		/*
		 * obtain and verify the current password (OLDAUTHTOK) for
		 * the user.
		 */
		char *Announce;

		D(("prelim check"));

		if (_unix_blankpasswd(ctrl, user)) {
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return PAM_SUCCESS;
		} else if (off(UNIX__IAMROOT, ctrl)) {

			/* instruct user what is happening */
#define greeting "Changing password for "
			Announce = (char *) malloc(sizeof(greeting) + strlen(user));
			if (Announce == NULL) {
				_log_err(LOG_CRIT, pamh,
				         "password - out of memory");
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return PAM_BUF_ERR;
			}
			(void) strcpy(Announce, greeting);
			(void) strcpy(Announce + sizeof(greeting) - 1, user);
#undef greeting

			lctrl = ctrl;
			set(UNIX__OLD_PASSWD, lctrl);
			retval = _unix_read_password(pamh, lctrl
						     ,Announce
					     ,"(current) UNIX password: "******"password - (old) token not obtained");
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return retval;
			}
			/* verify that this is the password for this user */

			retval = _unix_verify_password(pamh, user, pass_old, ctrl);
		} else {
			D(("process run by root so do nothing this time around"));
			pass_old = NULL;
			retval = PAM_SUCCESS;	/* root doesn't have too */
		}

		if (retval != PAM_SUCCESS) {
			D(("Authentication failed"));
			pass_old = NULL;
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
		pass_old = NULL;
		if (retval != PAM_SUCCESS) {
			_log_err(LOG_CRIT, pamh,
			         "failed to set PAM_OLDAUTHTOK");
		}
		retval = _unix_verify_shadow(user, ctrl);
		if (retval == PAM_AUTHTOK_ERR) {
			if (off(UNIX__IAMROOT, ctrl))
				_make_remark(pamh, ctrl, PAM_ERROR_MSG,
					    "You must wait longer to change your password");
			else
				retval = PAM_SUCCESS;
		}
	} else if (on(UNIX__UPDATE, ctrl)) {
		/*
		 * tpass is used below to store the _pam_md() return; it
		 * should be _pam_delete()'d.
		 */

		char *tpass = NULL;
		int retry = 0;

		/*
		 * obtain the proposed password
		 */

		D(("do update"));

		/*
		 * 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(UNIX_NOT_SET_PASS, ctrl)) {
			retval = pam_get_item(pamh, PAM_OLDAUTHTOK
					      ,(const void **) &pass_old);
		} else {
			retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK
					      ,(const void **) &pass_old);
			if (retval == PAM_NO_MODULE_DATA) {
				retval = PAM_SUCCESS;
				pass_old = NULL;
			}
		}
		D(("pass_old [%s]", pass_old));

		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh, "user not authenticated");
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		retval = _unix_verify_shadow(user, ctrl);
		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh, "user not authenticated 2");
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		D(("get new password now"));

		lctrl = ctrl;

		if (on(UNIX_USE_AUTHTOK, lctrl)) {
			set(UNIX_USE_FIRST_PASS, lctrl);
		}
		retry = 0;
		retval = PAM_AUTHTOK_ERR;
		while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) {
			/*
			 * use_authtok is to force the use of a previously entered
			 * password -- needed for pluggable password strength checking
			 */

			retval = _unix_read_password(pamh, lctrl
						     ,NULL
					     ,"Enter new UNIX password: "******"Retype new UNIX password: "******"password - new password not obtained");
				}
				pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return retval;
			}
			D(("returned to _unix_chauthtok"));

			/*
			 * 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_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
		}

		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh,
			         "new password not acceptable");
			_pam_overwrite(pass_new);
			_pam_overwrite(pass_old);
			pass_new = pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		/*
		 * By reaching here we have approved the passwords and must now
		 * rebuild the password database file.
		 */

		/*
		 * First we encrypt the new password.
		 */

		if (on(UNIX_MD5_PASS, ctrl)) {
			tpass = crypt_md5_wrapper(pass_new);
		} else {
			/*
			 * Salt manipulation is stolen from Rick Faith's passwd
			 * program.  Sorry Rick :) -- alex
			 */

			time_t tm;
			char salt[3];

			time(&tm);
			salt[0] = bin_to_ascii(tm & 0x3f);
			salt[1] = bin_to_ascii((tm >> 6) & 0x3f);
			salt[2] = '\0';

			if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) {
				/* 
				 * to avoid using the _extensions_ of the bigcrypt()
				 * function we truncate the newly entered password
				 */
				char *temp = malloc(9);
				char *e;

				if (temp == NULL) {
					_log_err(LOG_CRIT, pamh,
					         "out of memory for password");
					_pam_overwrite(pass_new);
					_pam_overwrite(pass_old);
					pass_new = pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
					ulckpwdf();
#endif
					return PAM_BUF_ERR;
				}
				/* copy first 8 bytes of password */
				strncpy(temp, pass_new, 8);
				temp[8] = '\0';

				/* no longer need cleartext */
				e = bigcrypt(temp, salt);
				tpass = x_strdup(e);

				_pam_overwrite(e);
				_pam_delete(temp);	/* tidy up */
			} else {
				char *e;

				/* no longer need cleartext */
				e = bigcrypt(pass_new, salt);
				tpass = x_strdup(e);

				_pam_overwrite(e);
			}
		}

		D(("password processed"));

		/* update the password database(s) -- race conditions..? */

		retval = _do_setpass(pamh, user, pass_old, tpass, ctrl,
		                     remember);
		_pam_overwrite(pass_new);
		_pam_overwrite(pass_old);
		_pam_delete(tpass);
		pass_old = pass_new = NULL;
	} else {		/* something has broken with the module */
Example #28
0
int pam_sm_authenticate(pam_handle_t *pamh, int flags,
                        int argc, const char **argv)
{
    unsigned int ctrl;
    int retval, *ret_data = NULL;
    SAM_ACCOUNT *sampass = NULL;
    extern BOOL in_client;
    const char *name;
    void (*oldsig_handler)(int);
    BOOL found;

    /* Points to memory managed by the PAM library. Do not free. */
    char *p = NULL;


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

    ctrl = set_ctrl(flags, argc, argv);

    /* Get a few bytes so we can pass our return value to
       pam_sm_setcred(). */
    ret_data = malloc(sizeof(int));

    /* get the username */
    retval = pam_get_user( pamh, &name, "Username: "******"auth: could not identify user");
        }
        AUTH_RETURN;
    }
    if (on( SMB_DEBUG, ctrl )) {
        _log_err( LOG_DEBUG, "username [%s] obtained", name );
    }

    /* 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" );
        retval = PAM_AUTHINFO_UNAVAIL;
        AUTH_RETURN;
    }

    pdb_init_sam(&sampass);
    
    found = pdb_getsampwnam( sampass, name );

    if (on( SMB_MIGRATE, ctrl )) {
	retval = _smb_add_user(pamh, ctrl, name, sampass, found);
	pdb_free_sam(&sampass);
	AUTH_RETURN;
    }

    if (!found) {
        _log_err(LOG_ALERT, "Failed to find entry for user %s.", name);
        retval = PAM_USER_UNKNOWN;
	pdb_free_sam(&sampass);
	sampass = NULL;
        AUTH_RETURN;
    }
   
    /* if this user does not have a password... */

    if (_smb_blankpasswd( ctrl, sampass )) {
        pdb_free_sam(&sampass);
        retval = PAM_SUCCESS;
        AUTH_RETURN;
    }

    /* get this user's authentication token */

    retval = _smb_read_password(pamh, ctrl, NULL, "Password: "******"auth: no password provided for [%s]"
		 , name);
        pdb_free_sam(&sampass);
        AUTH_RETURN;
    }

    /* verify the password of this user */

    retval = _smb_verify_password( pamh, sampass, p, ctrl );
    pdb_free_sam(&sampass);
    p = NULL;
    AUTH_RETURN;
}
Example #29
0
int pam_sm_authenticate(pam_handle_t *pamh, int flags,
                        int argc, const char **argv)
{
	unsigned int ctrl;
	int retval, *ret_data = NULL;
	struct samu *sampass = NULL;
	const char *name;
	void (*oldsig_handler)(int) = NULL;
	bool found;

	/* Points to memory managed by the PAM library. Do not free. */
	char *p = NULL;

	/* Samba initialization. */
	load_case_tables();
        lp_set_in_client(True);

	ctrl = set_ctrl(pamh, flags, argc, argv);

	/* Get a few bytes so we can pass our return value to
		pam_sm_setcred(). */
	ret_data = SMB_MALLOC_P(int);

	/* we need to do this before we call AUTH_RETURN */
	/* 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);

	/* get the username */
	retval = pam_get_user( pamh, &name, "Username: "******"auth: could not identify user");
		}
		AUTH_RETURN;
	}
	if (on( SMB_DEBUG, ctrl )) {
		_log_err(pamh, LOG_DEBUG, "username [%s] obtained", name );
	}

	if (geteuid() != 0) {
		_log_err(pamh, LOG_DEBUG, "Cannot access samba password database, not running as root.");
		retval = PAM_AUTHINFO_UNAVAIL;
		AUTH_RETURN;
	}

	if (!initialize_password_db(True, NULL)) {
		_log_err(pamh, LOG_ALERT, "Cannot access samba password database" );
		retval = PAM_AUTHINFO_UNAVAIL;
		AUTH_RETURN;
	}

	sampass = samu_new( NULL );
    	if (!sampass) {
		_log_err(pamh, LOG_ALERT, "Cannot talloc a samu struct" );
		retval = nt_status_to_pam(NT_STATUS_NO_MEMORY);
		AUTH_RETURN;
	}

	found = pdb_getsampwnam( sampass, name );

	if (on( SMB_MIGRATE, ctrl )) {
		retval = _smb_add_user(pamh, ctrl, name, sampass, found);
		TALLOC_FREE(sampass);
		AUTH_RETURN;
	}

	if (!found) {
		_log_err(pamh, LOG_ALERT, "Failed to find entry for user %s.", name);
		retval = PAM_USER_UNKNOWN;
		TALLOC_FREE(sampass);
		sampass = NULL;
		AUTH_RETURN;
	}

	/* if this user does not have a password... */

	if (_smb_blankpasswd( ctrl, sampass )) {
		TALLOC_FREE(sampass);
		retval = PAM_SUCCESS;
		AUTH_RETURN;
	}

	/* get this user's authentication token */

	retval = _smb_read_password(pamh, ctrl, NULL, "Password: "******"auth: no password provided for [%s]", name);
		TALLOC_FREE(sampass);
		AUTH_RETURN;
	}

	/* verify the password of this user */

	retval = _smb_verify_password( pamh, sampass, p, ctrl );
	TALLOC_FREE(sampass);
	p = NULL;
	AUTH_RETURN;
}
Example #30
0
/* Helper function for adding a user to the db. */
static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl,
                         const char *name, SAM_ACCOUNT *sampass, BOOL exist)
{
    pstring err_str;
    pstring msg_str;
    const char *pass = NULL;
    int retval;

    err_str[0] = '\0';
    msg_str[0] = '\0';

    /* Get the authtok; if we don't have one, silently fail. */
    retval = pam_get_item( pamh, PAM_AUTHTOK, (const void **) &pass );

    if (retval != PAM_SUCCESS) {
	_log_err( LOG_ALERT
	          , "pam_get_item returned error to pam_sm_authenticate" );
	return PAM_AUTHTOK_RECOVER_ERR;
    } else if (pass == NULL) {
	return PAM_AUTHTOK_RECOVER_ERR;
    }

    /* Add the user to the db if they aren't already there. */
   if (!exist) {
	retval = local_password_change( name, LOCAL_ADD_USER,
	                                 pass, err_str,
	                                 sizeof(err_str),
	                                 msg_str, sizeof(msg_str) );
	if (!retval && *err_str)
	{
	    err_str[PSTRING_LEN-1] = '\0';
	    make_remark( pamh, ctrl, PAM_ERROR_MSG, err_str );
	}
	else if (*msg_str)
	{
	    msg_str[PSTRING_LEN-1] = '\0';
	    make_remark( pamh, ctrl, PAM_TEXT_INFO, msg_str );
	}
	pass = NULL;

	return PAM_IGNORE;
   }
   else {
    /* Change the user's password IFF it's null. */
    if ((pdb_get_lanman_passwd(sampass) == NULL) && (pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ))
    {
	retval = local_password_change( name, 0, pass, err_str, sizeof(err_str),
	                                 msg_str, sizeof(msg_str) );
	if (!retval && *err_str)
	{
	    err_str[PSTRING_LEN-1] = '\0';
	    make_remark( pamh, ctrl, PAM_ERROR_MSG, err_str );
	}
	else if (*msg_str)
	{
	    msg_str[PSTRING_LEN-1] = '\0';
	    make_remark( pamh, ctrl, PAM_TEXT_INFO, msg_str );
	}
    }
   }
    
    pass = NULL;

    return PAM_IGNORE;
}