Esempio n. 1
0
/* sets a date, mapping given date into standard form if needed */
int
set_date(
    char *	date)
{
    char *cmd = NULL;
    char *qdisk_path;

    clear_dir_list();

    cmd = stralloc2("DATE ", date);
    if (converse(cmd) == -1)
	exit(1);

    /* if a host/disk/directory is set, then check if that directory
       is still valid at the new date, and if not set directory to
       mount_point */
    if (disk_path != NULL) {
	qdisk_path = quote_string(disk_path);
	cmd = newstralloc2(cmd, "OISD ", qdisk_path);
	amfree(qdisk_path);
	if (exchange(cmd) == -1)
	    exit(1);
	if (server_happy())
	{
	    suck_dir_list_from_server();
	}
	else
	{
	    g_printf(_("No index records for cwd on new date\n"));
	    g_printf(_("Setting cwd to mount point\n"));
	    disk_path = newstralloc(disk_path, "/");	/* fake it */
	    clear_dir_list();
	}
    }
    amfree(cmd);
    return 0;
}
Esempio n. 2
0
PAM_EXTERN
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
			,const char **argv)
{
    int retval, anon=0, ctrl;
    const char *user;
    char *users=NULL;

    /*
     * this module checks if the user name is ftp or annonymous. If
     * this is the case, it can set the PAM_RUSER to the entered email
     * address and SUCCEEDS, otherwise it FAILS.
     */

    ctrl = _pam_parse(argc, argv, &users);

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

    if (!(ctrl & PAM_NO_ANON)) {
	anon = lookup(user, users, &user);
    }

    if (anon) {
	retval = pam_set_item(pamh, PAM_USER, (const void *)user);
	if (retval != PAM_SUCCESS || user == NULL) {
	    _pam_log(LOG_ERR, "user resetting failed");
	    return PAM_USER_UNKNOWN;
	}
    }

    /*
     * OK. we require an email address for user or the user's password.
     * - build conversation and get their input.
     */

    {
	struct pam_message msg[1], *mesg[1];
	struct pam_response *resp=NULL;
	const char *token;
	char *prompt=NULL;
	int i=0;

	if (!anon) {
	    prompt = malloc(strlen(PLEASE_ENTER_PASSWORD) + strlen(user));
	    if (prompt == NULL) {
		D(("out of memory!?"));
		return PAM_BUF_ERR;
	    } else {
		sprintf(prompt, PLEASE_ENTER_PASSWORD, user);
		msg[i].msg = prompt;
	    }
	} else {
	    msg[i].msg = GUEST_LOGIN_PROMPT;
	}

	msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
	mesg[i] = &msg[i];

	retval = converse(pamh, ++i, mesg, &resp);
	if (prompt) {
	    _pam_overwrite(prompt);
	    _pam_drop(prompt);
	}

	if (retval != PAM_SUCCESS) {
	    if (resp != NULL)
		_pam_drop_reply(resp,i);
	    return ((retval == PAM_CONV_AGAIN)
		    ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
	}

	if (anon) {
	    /* XXX: Some effort should be made to verify this email address! */

	    if (!(ctrl & PAM_IGNORE_EMAIL)) {
		token = strtok(resp->resp, "@");
		retval = pam_set_item(pamh, PAM_RUSER, token);

		if ((token) && (retval == PAM_SUCCESS)) {
		    token = strtok(NULL, "@");
		    retval = pam_set_item(pamh, PAM_RHOST, token);
		}
	    }

	    /* we are happy to grant annonymous access to the user */
	    retval = PAM_SUCCESS;

	} else {
	    /*
	     * we have a password so set AUTHTOK
	     */

	    (void) pam_set_item(pamh, PAM_AUTHTOK, resp->resp);

	    /*
	     * this module failed, but the next one might succeed with
	     * this password.
	     */

	    retval = PAM_AUTH_ERR;
	}

	if (resp) {                                      /* clean up */
	    _pam_drop_reply(resp, i);
	}

	/* success or failure */

	return retval;
    }
}
Esempio n. 3
0
void
set_host(
    const char *host)
{
    char *cmd = NULL;
    struct hostent *hp = NULL;
    char **hostp;
    int found_host = 0;
    char *uqhost = unquote_string(host);

    if (is_extract_list_nonempty())
    {
	g_printf(_("Must clear extract list before changing host\n"));
	amfree(uqhost);
	return;
    }

    /*
     * The idea here is to try as many permutations of the hostname
     * as we can imagine.  The server will reject anything it doesn't
     * recognize.
     */

    cmd = stralloc2("HOST ", uqhost);
    if (converse(cmd) == -1)
	exit(1);
    if (server_happy())
	found_host = 1;

    /*
     * Try converting the given host to a fully qualified, canonical
     * name.
     */
    if (!found_host) {
	if ((hp = gethostbyname(uqhost)) != NULL) {
	    host = hp->h_name;
	    g_printf(_("Trying host %s ...\n"), host);
	    cmd = newstralloc2(cmd, "HOST ", host);
	    if (converse(cmd) == -1)
		exit(1);
	    if(server_happy())
		found_host = 1;
	}
    }

    /*
     * Since we have them, try any CNAMEs that were traversed from uqhost
     * to the canonical name (this assumes gethostbyname was called above)
     */
    if (!found_host) {
	if (hp) {
	    for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
	    {
		g_printf(_("Trying host %s ...\n"), host);
		cmd = newstralloc2(cmd, "HOST ", host);
		if (converse(cmd) == -1)
		    exit(1);
		if(server_happy())
		{
		    found_host = 1;
		    break;
		}
	    }
	}
    }

    /* Try looking up the canonical name of the host */
    if (!found_host) {
	char *canonname;
	int result;

	result = resolve_hostname(uqhost, 0, NULL, &canonname);
	if (result == 0 && canonname) {
	    host = canonname;
	    g_printf(_("Trying host %s ...\n"), host);
	    cmd = newstralloc2(cmd, "HOST ", host);
	    if (converse(cmd) == -1)
		exit(1);
	    if(server_happy())
		found_host = 1;
	}
    }

    if(found_host) {
	dump_hostname = newstralloc(dump_hostname, host);
	amfree(disk_name);
	amfree(mount_point);
	amfree(disk_path);
	clear_dir_list();
    }
    amfree(cmd);
    amfree(uqhost);
}
Esempio n. 4
0
void
set_disk(
    char *	dsk,
    char *	mtpt)
{
    char *cmd = NULL;
    char *qdsk;
    char *uqdsk;
    char *uqmtpt = NULL;

    if (is_extract_list_nonempty())
    {
	g_printf(_("Must clear extract list before changing disk\n"));
	return;
    }

    /* if mount point specified, check it is valid */
    if (mtpt != NULL) {
	uqmtpt = unquote_string(mtpt);
	if (*mtpt != '/') {
	    g_printf(_("Mount point \"%s\" invalid - must start with /\n"), uqmtpt);
	    amfree(uqmtpt);
	    return;
	}
    }

    clear_dir_list();
    uqdsk = unquote_string(dsk);
    qdsk = quote_string(uqdsk);
    cmd = stralloc2("DISK ", qdsk);
    amfree(qdsk);
    if (converse(cmd) == -1)
	exit(1);
    amfree(cmd);

    if (!server_happy()) {
	amfree(uqmtpt);
	amfree(uqdsk);
	return;
    }

    disk_name = newstralloc(disk_name, uqdsk);
    if (mtpt == NULL)
    {
	/* mount point not specified */
	if (*uqdsk == '/')
	{
	    /* disk specified by mount point, hence use it */
	    mount_point = newstralloc(mount_point, uqdsk);
	}
	else
	{
	    /* device name given, use '/' because nothing better */
	    mount_point = newstralloc(mount_point, "/");
	}
    }
    else
    {
	/* mount point specified */
	mount_point = newstralloc(mount_point, uqmtpt);
    }

    /* set the working directory to the mount point */
    /* there is the possibility that there are no index records for the
       disk for the given date, hence setting the directory to the
       mount point will fail. Preempt this by checking first so we can write
       a more informative message. */
    if (exchange("OISD /") == -1)
	exit(1);
    if (server_happy())
    {
	disk_path = newstralloc(disk_path, "/");
	suck_dir_list_from_server();	/* get list of directory contents */
    }
    else
    {
	g_printf(_("No index records for disk for specified date\n"));
	g_printf(_("If date correct, notify system administrator\n"));
	disk_path = newstralloc(disk_path, "/");	/* fake it */
	clear_dir_list();
    }
    amfree(uqmtpt);
    amfree(uqdsk);

    if (am_has_feature(indexsrv_features, fe_amindexd_DLE)) {
	char *dle_str;
	char *errmsg = NULL;

	cmd = stralloc("DLE");
	if (exchange(cmd) == -1)
	    exit(1);
	amfree(cmd);

	if (!server_happy())
	    return;

	dle_str = reply_line();
	if (BSTRNCMP(dle_str+4, "NODLE") == 0) {
	    dump_dle = NULL;
	} else {
	    dle_str = unquote_string(dle_str+4);
	    dump_dle = amxml_parse_node_CHAR(dle_str, &errmsg);
	    amfree(dle_str);
	}
    }
}
Esempio n. 5
0
/* authenticates user on remote TACACS+ server
 * returns PAM_SUCCESS if the supplied username and password
 * pair is valid
 */
PAM_EXTERN
int pam_sm_authenticate (pam_handle_t * pamh, int flags,
    int argc, const char **argv) {

    int ctrl, retval;
    char *user;
    char *pass;
    char *tty;
    char *r_addr;
    int srv_i;
    int tac_fd, status, msg, communicating;

    user = pass = tty = r_addr = NULL;

    ctrl = _pam_parse(argc, argv);

    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)",
            __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT);

    if ((user = _pam_get_user(pamh)) == NULL)
        return PAM_USER_UNKNOWN;

    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user);

    // read config file
    _read_config(ctrl);
    
    retval = tacacs_get_password (pamh, flags, ctrl, &pass);
    if (retval != PAM_SUCCESS || pass == NULL || *pass == '\0') {
        _pam_log(LOG_ERR, "unable to obtain password");
        xfree(pass);
        return PAM_CRED_INSUFFICIENT;
    }

    retval = pam_set_item (pamh, PAM_AUTHTOK, pass);
    if (retval != PAM_SUCCESS) {
        _pam_log(LOG_ERR, "unable to set password");
        xfree(pass);
        return PAM_CRED_INSUFFICIENT;
    }

    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: password obtained", __FUNCTION__);

    tty = _pam_get_terminal(pamh);
    if (!strncmp(tty, "/dev/", 5))
        tty += 5;
    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: tty [%s] obtained", __FUNCTION__, tty);

    r_addr = _pam_get_rhost(pamh);
    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: rhost [%s] obtained", __FUNCTION__, r_addr);

    status = PAM_AUTHINFO_UNAVAIL;
    for (srv_i = 0; srv_i < tac_srv_no; srv_i++) {
        if (ctrl & PAM_TAC_DEBUG)
            syslog(LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i );

        tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout);
        if (tac_fd < 0) {
            _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i);
            continue;
        }
        if (tac_authen_send(tac_fd, user, pass, tty, r_addr, TAC_PLUS_AUTHEN_LOGIN) < 0) {
            close(tac_fd);
            _pam_log(LOG_ERR, "error sending auth req to TACACS+ server");
            continue;
        }
        communicating = 1;
        while (communicating) {
            struct areply re = { .attr = NULL, .msg = NULL, status = 0, flags = 0 };
            struct pam_message conv_msg = { .msg_style = 0, .msg = NULL };
            struct pam_response *resp = NULL;

            msg = tac_authen_read(tac_fd, &re);

            if (NULL != re.msg) {
                conv_msg.msg = re.msg;
            }

            /* talk the protocol */
            switch (msg) {
                case TAC_PLUS_AUTHEN_STATUS_PASS:
                    /* success */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_PASS");
  
                    if (NULL != conv_msg.msg) {
                        int retval = -1;

                        conv_msg.msg_style = PAM_TEXT_INFO;
                        retval = converse(pamh, 1, &conv_msg, &resp);
                        if (PAM_SUCCESS == retval) {
                            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                                syslog(LOG_DEBUG, "send msg=\"%s\"", conv_msg.msg);
                        }
                        else {
                            _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d",
                                     __FUNCTION__, conv_msg.msg, retval);
                        }

                    }
                    status = PAM_SUCCESS;
                    communicating = 0;
                    if (active_server.addr != NULL)
                    {
                        xfree(active_server.addr);
                    }
                    active_server.addr = (struct addrinfo*)xcalloc(1, sizeof(struct addrinfo));
                    bcopy(tac_srv[srv_i].addr, active_server.addr, sizeof(struct addrinfo));
                    if (active_server.key != NULL)
                    {
                        xfree(active_server.key);
                    }
                    active_server.key = xstrdup(tac_srv[srv_i].key);

                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i);

                    break;

                case TAC_PLUS_AUTHEN_STATUS_FAIL:
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_FAIL");

                    if (NULL != conv_msg.msg) {
                        int retval = -1;

                        conv_msg.msg_style = PAM_ERROR_MSG;
                        retval = converse(pamh, 1, &conv_msg, &resp);
                        if (PAM_SUCCESS == retval) {
                            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                                syslog(LOG_DEBUG, "send msg=\"%s\"", conv_msg.msg);
                        }
                        else {
                            _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d",
                                     __FUNCTION__, conv_msg.msg, retval);
                        }

                    }
                    status = PAM_AUTH_ERR;
                    communicating = 0;

                    _pam_log(LOG_ERR, "auth failed: %d", msg);

                    break;

                case TAC_PLUS_AUTHEN_STATUS_GETDATA:
                    if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETDATA");

                    if (NULL != conv_msg.msg) {
                        int retval = -1;
                        int echo_off = (0x1 == (re.flags & 0x1));
                        
                        conv_msg.msg_style = echo_off ? PAM_PROMPT_ECHO_OFF : PAM_PROMPT_ECHO_ON;
                        retval = converse(pamh, 1, &conv_msg, &resp);
                        if (PAM_SUCCESS == retval) {
                            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG)) 
                                syslog(LOG_DEBUG, "sent msg=\"%s\", resp=\"%s\"",
                                       conv_msg.msg, resp->resp);

                            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                                syslog(LOG_DEBUG, "%s: calling tac_cont_send", __FUNCTION__);

                            if (0 > tac_cont_send_seq(tac_fd, resp->resp, re.seq_no + 1)) {
                                _pam_log(LOG_ERR, "error sending continue req to TACACS+ server");
                                status = PAM_AUTH_ERR;
                                communicating = 0;
                            }
                        }
                        else {
                            _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d (%s)",
                                     __FUNCTION__, conv_msg.msg, retval, pam_strerror(pamh, retval));
                            status = PAM_AUTH_ERR;
                            communicating = 0;
                        }
                    }
                    else { 
                        syslog(LOG_ERR, "GETDATA response with no message, returning PAM_AUTH_ERR");

                        status = PAM_AUTH_ERR;
                        communicating = 0;
                    }

                    break;

                case TAC_PLUS_AUTHEN_STATUS_GETUSER:
                    /* not implemented */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETUSER");

                    communicating = 0;
                    break;

                case TAC_PLUS_AUTHEN_STATUS_GETPASS:
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETPASS");

                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "%s: tac_cont_send called", __FUNCTION__);

                    if (tac_cont_send(tac_fd, pass) < 0) {
                        _pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
                        communicating = 0;
                    }
                    /* continue the while loop; go read tac response */
                    break;

                case TAC_PLUS_AUTHEN_STATUS_RESTART:
                    /* try it again */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_RESTART");

                    /*
                     * not implemented
                     * WdJ: I *think* you can just do tac_authen_send(user, pass) again
                     *      but I'm not sure
                     */
                    communicating = 0;
                    break;

                case TAC_PLUS_AUTHEN_STATUS_ERROR:
                    /* server has problems */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_ERROR");

                    communicating = 0;
                    break;

                case TAC_PLUS_AUTHEN_STATUS_FOLLOW:
                    /* server tells to try a different server address */
                    /* not implemented */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_FOLLOW");

                    communicating = 0;
                    break;

                default:
                    if (msg < 0) {
                        /* connection error */
                        communicating = 0;
                        if (ctrl & PAM_TAC_DEBUG)
                            syslog(LOG_DEBUG, "error communicating with tacacs server");
                        break;
                    }

                    /* unknown response code */
                    communicating = 0;
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: unknown response 0x%02x", msg);
            }

            if (NULL != resp)
            {
                if (resp->resp != NULL)
                {
                    xfree(resp->resp);
                }
                xfree(resp);
            }
                
            if (re.msg != NULL)
            {
                xfree(re.msg);
            }

        }    /* end while(communicating) */
        close(tac_fd);

        if (status == PAM_SUCCESS || status == PAM_AUTH_ERR)
            break;
    }
    if (status != PAM_SUCCESS && status != PAM_AUTH_ERR)
        _pam_log(LOG_ERR, "no more servers to connect");

    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: exit with pam status: %d", __FUNCTION__, status);

    if (NULL != pass) {
        bzero(pass, strlen (pass));
        xfree(pass);
        pass = NULL;
    }

    return status;
}    /* pam_sm_authenticate */


/* no-op function to satisfy PAM authentication module */
PAM_EXTERN
int pam_sm_setcred (pam_handle_t * pamh, int flags,
    int argc, const char **argv) {

    int ctrl = _pam_parse (argc, argv);

    if (ctrl & PAM_TAC_DEBUG)
        syslog (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)"
            , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT);

    return PAM_SUCCESS;
}    /* pam_sm_setcred */


/* authorizes user on remote TACACS+ server, i.e. checks
 * his permission to access requested service
 * returns PAM_SUCCESS if the service is allowed
 */
PAM_EXTERN
int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags,
    int argc, const char **argv) {

    int retval, ctrl, status=PAM_AUTH_ERR;
    char *user;
    char *tty;
    char *r_addr;
    struct areply arep;
    struct tac_attrib *attr = NULL;
    int tac_fd;

    user = tty = r_addr = NULL;
    memset(&arep, 0, sizeof(arep));

    /* this also obtains service name for authorization
       this should be normally performed by pam_get_item(PAM_SERVICE)
       but since PAM service names are incompatible TACACS+
       we have to pass it via command line argument until a better
       solution is found ;) */
    ctrl = _pam_parse (argc, argv);

    if (ctrl & PAM_TAC_DEBUG)
        syslog (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)"
            , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT);

    if ((user = _pam_get_user(pamh)) == NULL)
        return PAM_USER_UNKNOWN;

    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: username obtained [%s]", __FUNCTION__, user);

    // read config file
    _read_config(ctrl);

    tty = _pam_get_terminal(pamh);
    if(!strncmp(tty, "/dev/", 5))
        tty += 5;
    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: tty obtained [%s]", __FUNCTION__, tty);

    r_addr = _pam_get_rhost(pamh);
    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: rhost obtained [%s]", __FUNCTION__, r_addr);

    /* checks if user has been successfully authenticated
       by TACACS+; we cannot solely authorize user if it hasn't
       been authenticated or has been authenticated by method other
       than TACACS+ */
    if(active_server.addr == NULL) {
        _pam_log (LOG_ERR, "user not authenticated by TACACS+");
        return PAM_AUTH_ERR;
    }
    if (ctrl & PAM_TAC_DEBUG)
        syslog (LOG_DEBUG, "%s: active server is [%s]", __FUNCTION__,
            tac_ntop(active_server.addr->ai_addr));

    /* checks for specific data required by TACACS+, which should
       be supplied in command line  */
    if(!*tac_service) {
        _pam_log (LOG_ERR, "SM: TACACS+ service type not configured");
        return PAM_AUTH_ERR;
    }
    if(!*tac_protocol) {
        _pam_log (LOG_ERR, "SM: TACACS+ protocol type not configured (IGNORED)");
    }

    tac_add_attrib(&attr, "service", tac_service);
    if(tac_protocol[0] != '\0')
        tac_add_attrib(&attr, "protocol", tac_protocol);
    
    tac_fd = tac_connect_single(active_server.addr, active_server.key, NULL, tac_timeout);
    if(tac_fd < 0) {
        _pam_log (LOG_ERR, "TACACS+ server unavailable");
        if(arep.msg != NULL)
            xfree (arep.msg);
        return PAM_AUTH_ERR;
    }

    retval = tac_author_send(tac_fd, user, tty, r_addr, attr);

    tac_free_attrib(&attr);

    if(retval < 0) {
        _pam_log (LOG_ERR, "error getting authorization");
        if(arep.msg != NULL)
            xfree (arep.msg);

        close(tac_fd);
        return PAM_AUTH_ERR;
    }

    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: sent authorization request", __FUNCTION__);

    tac_author_read(tac_fd, &arep);

    if(arep.status != AUTHOR_STATUS_PASS_ADD &&
        arep.status != AUTHOR_STATUS_PASS_REPL) {

        _pam_log (LOG_ERR, "TACACS+ authorisation failed for [%s]", user);
        if(arep.msg != NULL)
            xfree (arep.msg);

        close(tac_fd);
        return PAM_PERM_DENIED;
    }

    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: user [%s] successfully authorized", __FUNCTION__, user);

    status = PAM_SUCCESS;

    attr = arep.attr;
    while (attr != NULL)  {
        char attribute[attr->attr_len];
        char value[attr->attr_len];
        char *sep;

        sep = index(attr->attr, '=');
        if(sep == NULL)
            sep = index(attr->attr, '*');
        if(sep != NULL) {
            bcopy(attr->attr, attribute, attr->attr_len-strlen(sep));
            attribute[attr->attr_len-strlen(sep)] = '\0';
            bcopy(sep, value, strlen(sep));
            value[strlen(sep)] = '\0';

            size_t i;
            for (i = 0; attribute[i] != '\0'; i++) {
                attribute[i] = toupper(attribute[i]);
                if (attribute[i] == '-')
                    attribute[i] = '_';
            }

            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "%s: returned attribute `%s%s' from server", __FUNCTION__, attribute, value);

            /* make returned attributes available for other PAM modules via PAM environment */
            if (pam_putenv(pamh, strncat(attribute, value, strlen(value))) != PAM_SUCCESS)
                syslog(LOG_WARNING, "%s: unable to set PAM environment", __FUNCTION__);

        } else {
            syslog(LOG_WARNING, "%s: invalid attribute `%s', no separator", __FUNCTION__, attr->attr);
        }
        attr = attr->next;
    }

    /* free returned attributes */
    if(arep.attr != NULL)
        tac_free_attrib(&arep.attr);

    if(arep.msg != NULL)
        xfree (arep.msg);

    close(tac_fd);

    return status;
}    /* pam_sm_acct_mgmt */
Esempio n. 6
0
int do_manual_authentication(const cfg_t *cfg, const device_t *devices,
                             const unsigned n_devs, pam_handle_t *pamh) {
  u2fs_ctx_t *ctx_arr[n_devs];
  u2fs_auth_res_t *auth_result;
  u2fs_rc s_rc;
  char *response = NULL;
  char prompt[MAX_PROMPT_LEN];
  char *buf;
  int retval = -2;
  unsigned i = 0;

  if (u2fs_global_init(0) != U2FS_OK) {
    if (cfg->debug)
      D(cfg->debug_file, "Unable to initialize libu2f-server");
    return retval;
  }

  for (i = 0; i < n_devs; ++i) {

    if (u2fs_init(ctx_arr + i) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to initialize libu2f-server");
      return retval;
    }

    if ((s_rc = u2fs_set_origin(ctx_arr[i], cfg->origin)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set origin: %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_set_appid(ctx_arr[i], cfg->appid)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set appid: %s", u2fs_strerror(s_rc));
      return retval;
    }

    if (cfg->debug)
      D(cfg->debug_file, "Attempting authentication with device number %d", i + 1);

    if ((s_rc = u2fs_set_keyHandle(ctx_arr[i], devices[i].keyHandle)) !=
        U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set keyHandle: %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_set_publicKey(ctx_arr[i], devices[i].publicKey)) !=
        U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set publicKey %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_authentication_challenge(ctx_arr[i], &buf)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to produce authentication challenge: %s",
           u2fs_strerror(s_rc));
      return retval;
    }

    if (cfg->debug)
      D(cfg->debug_file, "Challenge: %s", buf);

    if (i == 0) {
      snprintf(prompt, sizeof(prompt),
                      "Now please copy-paste the below challenge(s) to "
                      "'u2f-host -aauthenticate -o %s'",
              cfg->origin);
      converse(pamh, PAM_TEXT_INFO, prompt);
    }
    converse(pamh, PAM_TEXT_INFO, buf);
    free(buf);
    buf = NULL;
  }

  converse(pamh, PAM_TEXT_INFO,
           "Now, please enter the response(s) below, one per line.");

  retval = -1;

  for (i = 0; i < n_devs; ++i) {
    snprintf(prompt, sizeof(prompt), "[%d]: ", i);
    response = converse(pamh, PAM_PROMPT_ECHO_ON, prompt);
    converse(pamh, PAM_TEXT_INFO, response);

    s_rc = u2fs_authentication_verify(ctx_arr[i], response, &auth_result);
    u2fs_free_auth_res(auth_result);
    if (s_rc == U2FS_OK) {
      retval = 1;
    }
    free(response);
    if (retval == 1) {
        break;
    }
  }

  for (i = 0; i < n_devs; ++i)
    u2fs_done(ctx_arr[i]);
  u2fs_global_done();

  return retval;
}
Esempio n. 7
0
/*
 * Talk to the server for authentication
 */
static int tac_auth_converse(int ctrl, int fd, int *sptr,
    char *pass, pam_handle_t * pamh) {
    int msg, status, flags;
    int ret = 1;
    struct areply re = { .attr = NULL, .msg = NULL, .status = 0, .flags = 0 };
    struct pam_message conv_msg = { .msg_style = 0, .msg = NULL };
    struct pam_response *resp = NULL;

    msg = tac_authen_read(fd, &re);

    if (NULL != re.msg) {
        conv_msg.msg = re.msg;
    }

    /* talk the protocol */
    switch (msg) {
        case TAC_PLUS_AUTHEN_STATUS_PASS:
            /* success */
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_PASS");
            if (NULL != conv_msg.msg) {
                int retval = -1;

                conv_msg.msg_style = PAM_TEXT_INFO;
                retval = converse(pamh, 1, &conv_msg, &resp);
                if (PAM_SUCCESS == retval) {
                    if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                        syslog(LOG_DEBUG, "send msg=\"%s\"", conv_msg.msg);
                }
                else {
                    _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d",
                             __func__, conv_msg.msg, retval);
                }
            }
            *sptr = PAM_SUCCESS;
            ret = 0;
            break;

        case TAC_PLUS_AUTHEN_STATUS_FAIL:
            /*
             * This can be a user unknown case, so we don't want to stop
             * trying other servers when we hit this case during authentication
             */
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_FAIL");
            if (NULL != conv_msg.msg) {
                int retval = -1;

                conv_msg.msg_style = PAM_ERROR_MSG;
                retval = converse(pamh, 1, &conv_msg, &resp);
                if (PAM_SUCCESS == retval) {
                    if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                        syslog(LOG_DEBUG, "send msg=\"%s\"", conv_msg.msg);
                }
                else {
                    _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d",
                             __func__, conv_msg.msg, retval);
                }
            }

            *sptr = PAM_AUTH_ERR;
            ret = 0;
            _pam_log(LOG_NOTICE, "auth failed %d", msg);
            break;

        case TAC_PLUS_AUTHEN_STATUS_GETDATA:
            /* not implemented */
            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETDATA");

            if (NULL != conv_msg.msg) {
                int retval = -1;
                int echo_off = (0x1 == (re.flags & 0x1));

                conv_msg.msg_style = echo_off ? PAM_PROMPT_ECHO_OFF : PAM_PROMPT_ECHO_ON;
                retval = converse(pamh, 1, &conv_msg, &resp);
                if (PAM_SUCCESS == retval) {
                    if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                        syslog(LOG_DEBUG, "sent msg=\"%s\", resp=\"%s\"",
                               conv_msg.msg, resp->resp);

                    if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                        syslog(LOG_DEBUG, "%s: calling tac_cont_send", __func__);

                    if (0 > tac_cont_send_seq(fd, resp->resp, re.seq_no + 1)) {
                        _pam_log(LOG_ERR, "error sending continue req to TACACS+ server");
                        status = PAM_AUTH_ERR;
                    }
                }
                else {
                    _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d (%s)",
                             __func__, conv_msg.msg, retval, pam_strerror(pamh, retval));
                    status = PAM_AUTH_ERR;
                }
            }
            else {
                syslog(LOG_ERR, "GETDATA response with no message, returning PAM_AUTH_ERR");

                status = PAM_AUTH_ERR;
            }

            ret = 0;
            break;

        case TAC_PLUS_AUTHEN_STATUS_GETUSER:
            /* not implemented */
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETUSER");

            ret = 0;
            break;

        case TAC_PLUS_AUTHEN_STATUS_GETPASS:
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETPASS");

            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "%s: tac_cont_send called", __func__);

            if (tac_cont_send(fd, pass) < 0) {
                _pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
                ret = 0;
                break;
            }
            /* continue the while loop; go read tac response */
            break;

        case TAC_PLUS_AUTHEN_STATUS_RESTART:
            /* try it again */
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_RESTART (not impl)");

            /*
             * not implemented
             * WdJ: I *think* you can just do tac_authen_send(user, pass) again
             *      but I'm not sure
             */
            ret = 0;
            break;

        case TAC_PLUS_AUTHEN_STATUS_ERROR:
            /* server has problems */
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_ERROR");

            ret = 0;
            break;

        case TAC_PLUS_AUTHEN_STATUS_FOLLOW:
            /* server tells to try a different server address */
            /* not implemented */
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_FOLLOW");

            ret = 0;
            break;

        default:
            if (msg < 0) {
                /* connection error */
                ret = 0;
                if (ctrl & PAM_TAC_DEBUG)
                    syslog(LOG_DEBUG, "error communicating with tacacs server");
                break;
            }

            /* unknown response code */
            ret = 0;
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "tacacs status: unknown response 0x%02x", msg);
    }

    if (NULL != resp) {
       free(resp->resp);
       free(resp);
    }

    if (NULL != re.msg);
        free(re.msg);

    return ret;
}

/*
 * Only acct and auth now; should handle all the cases here
 * Talk to the tacacs server for each type of transaction conversation
 */
static void talk_tac_server(int ctrl, int fd, char *user, char *pass,
                            char *tty, char *r_addr, struct tac_attrib **attr,
                            int *sptr, struct areply *reply,
                            pam_handle_t * pamh) {
    if(!pass && attr) {  /* acct, much simpler */
        int retval;
        struct areply arep;
        retval = tac_author_send(fd, user, tty, r_addr, *attr);
        if(retval < 0) {
            _pam_log (LOG_ERR, "error getting authorization");

            *sptr =  PAM_AUTH_ERR;
            return;
        }

        if (ctrl & PAM_TAC_DEBUG)
            syslog(LOG_DEBUG, "%s: sent authorization request for [%s]",
                __func__, user);

        arep.msg = NULL;
        tac_author_read(fd, &arep);
        if (reply)
            *reply = arep;

        if(arep.status != AUTHOR_STATUS_PASS_ADD &&
            arep.status != AUTHOR_STATUS_PASS_REPL) {
            /*
             * this is debug because we can get called for any user for
             * commands like sudo, not just tacacs users
             */
            *sptr = PAM_PERM_DENIED;
            _pam_log (LOG_ERR, "TACACS+ authorization failed for [%s] (status=%d)",
                user, arep.status);
            if(arep.msg != NULL && !reply)
                free (arep.msg); /*  if reply is set, caller will free */
        }
        else  {
            *sptr = PAM_SUCCESS;
        }
    }
    else if (pass)  { /* auth */
        if (tac_authen_send(fd, user, pass, tty, r_addr, TAC_PLUS_AUTHEN_LOGIN) < 0) {
            _pam_log(LOG_ERR, "error sending auth req to TACACS+ server");
        }
        else {
            while ( tac_auth_converse(ctrl, fd, sptr, pass, pamh))
                    ;
        }
    }
}


/*
 * find a responding tacacs server, and converse with it.
 * See comments at do_tac_connect() below
 */
static void find_tac_server(int ctrl, int *tacfd, char *user, char *pass,
                           char *tty, char *r_addr, struct tac_attrib **attr,
                           int *sptr, struct areply *reply, pam_handle_t * pamh) {
    int fd = -1, srv_i;

    for (srv_i = 0; srv_i < tac_srv_no; srv_i++) {
        if (ctrl & PAM_TAC_DEBUG)
            syslog(LOG_DEBUG, "%s: trying srv[%d] %s", __func__, srv_i,
                tac_srv[srv_i].addr ?
                tac_ntop(tac_srv[srv_i].addr->ai_addr) : "not set");

        fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL,
            __vrfname);
        if (fd < 0) {
            _pam_log(LOG_ERR, "connection to srv[%d] %s failed: %m", srv_i,
                tac_srv[srv_i].addr ?
                tac_ntop(tac_srv[srv_i].addr->ai_addr) : "not set");
            active_server.addr = NULL; /*  in case last in list */
            continue;
        }

        talk_tac_server(ctrl, fd, user, pass, tty, r_addr, attr, sptr,
            reply, pamh);

        if (*sptr == PAM_SUCCESS || *sptr == PAM_AUTH_ERR ||
            *sptr == PAM_PERM_DENIED) {
            if (ctrl & PAM_TAC_DEBUG)
                syslog(LOG_DEBUG, "%s: srv[%d] %s, pam_status=%d", __func__,
                   srv_i, tac_ntop(tac_srv[srv_i].addr->ai_addr), *sptr);
            if (*sptr == PAM_SUCCESS) {
                if (active_server.addr == NULL) {
                    active_server.addr = tac_srv[srv_i].addr;
                    active_server.key = tac_srv[srv_i].key;
                }
                break;
            }
            /*  else try other servers, if any. On errs, won't need fd */
        }
        else /*  in case end of list */
            active_server.addr = NULL;

        close(fd);
        fd = -1;
    }
    *tacfd = fd;
}

/*
 * We have to make a new connection each time, because libtac is single
 * threaded (doesn't support multiple connects at the same time due to
 * use of globals), and doesn't have support for persistent connections.
 * That's fixable, but not worth the effort at this point.
 *
 * Trying to make this common code is ugly, but worth it to simplify
 * maintenance and debugging.
 *
 * The problem is that the definition allows for multiple tacacs
 * servers to be consulted, but a lot of the code was written such
 * that once a server is found that responds, it keeps using it.
 * That means when we are finding a server we need to do the full sequence.
 * The related issue is that the lower level code can't communicate
 * with multiple servers at the same time, and can't keep a connection
 * open.
 *
 * TODO: Really should have a structure to pass user, pass, tty, and r_addr
 * around everywhere.
 */
static int do_tac_connect(int ctrl, int *tacfd, char *user, char *pass,
                          char *tty, char *r_addr, struct tac_attrib **attr,
                          struct areply *reply, pam_handle_t * pamh) {
    int status = PAM_AUTHINFO_UNAVAIL, fd;

    if (active_server.addr == NULL) { /* find a server with the info we want */
        find_tac_server(ctrl, &fd, user, pass, tty, r_addr, attr, &status,
            reply, pamh);
    }
    else { /* connect to the already chosen server, so we get
            * consistent results.  */
        if (ctrl & PAM_TAC_DEBUG)
            syslog(LOG_DEBUG, "%s: use previous server %s", __func__,
               tac_ntop(active_server.addr->ai_addr));

        fd = tac_connect_single(active_server.addr, active_server.key, NULL,
            __vrfname);
        if (fd < 0)
            _pam_log(LOG_ERR, "reconnect failed: %m");
        else
            talk_tac_server(ctrl, fd, user, pass, tty, r_addr, attr, &status,
                reply, pamh);
    }

    /*
     * this is debug because we can get called for any user for
     * commands like sudo, not just tacacs users, so it's not an
     * error to fail here.  The caller can handle the logging.
     */
    if ((ctrl & PAM_TAC_DEBUG) && status != PAM_SUCCESS &&
        status != PAM_AUTH_ERR)
        _pam_log(LOG_ERR, "no more servers to connect");
    if (tacfd)
        *tacfd = fd; /* auth caller needs fd */
    else if (fd != -1)
        close(fd); /* acct caller doesn't need connection */
    return status;
}
Esempio n. 8
0
int
main(
    int		argc,
    char **	argv)
{
    in_port_t my_port;
    struct servent *sp;
    int i;
    time_t timer;
    char *lineread = NULL;
    struct sigaction act, oact;
    extern char *optarg;
    extern int optind;
    char cwd[STR_SIZE], *dn_guess = NULL, *mpt_guess = NULL;
    char *service_name;
    char *line = NULL;
    struct tm *tm;

    /*
     * Configure program for internationalization:
     *   1) Only set the message locale for now.
     *   2) Set textdomain for all amanda related programs to "amanda"
     *      We don't want to be forced to support dozens of message catalogs.
     */  
    setlocale(LC_MESSAGES, "C");
    textdomain("amanda"); 

    safe_fd(-1, 0);

    set_pname("amoldrecover");

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    dbopen(DBG_SUBDIR_CLIENT);

    localhost = g_malloc(MAX_HOSTNAME_LENGTH+1);
    if (gethostname(localhost, MAX_HOSTNAME_LENGTH) != 0) {
	error(_("cannot determine local host name\n"));
	/*NOTREACHED*/
    }
    localhost[MAX_HOSTNAME_LENGTH] = '\0';

    g_free(config);
    config = g_strdup(DEFAULT_CONFIG);

    dbrename(config, DBG_SUBDIR_CLIENT);

    check_running_as(RUNNING_AS_ROOT);

    amfree(server_name);
    server_name = getenv("AMANDA_SERVER");
    if(!server_name) server_name = DEFAULT_SERVER;
    server_name = g_strdup(server_name);

    amfree(tape_server_name);
    tape_server_name = getenv("AMANDA_TAPESERVER");
    if(!tape_server_name) tape_server_name = DEFAULT_TAPE_SERVER;
    tape_server_name = g_strdup(tape_server_name);

    config_init(CONFIG_INIT_CLIENT, NULL);

    if (config_errors(NULL) >= CFGERR_WARNINGS) {
	config_print_errors();
	if (config_errors(NULL) >= CFGERR_ERRORS) {
	    g_critical(_("errors processing config file"));
	}
    }

    if (argc > 1 && argv[1][0] != '-')
    {
	/*
	 * If the first argument is not an option flag, then we assume
	 * it is a configuration name to match the syntax of the other
	 * Amanda utilities.
	 */
	char **new_argv;

	new_argv = (char **) g_malloc((size_t)((argc + 1 + 1) * sizeof(*new_argv)));
	new_argv[0] = argv[0];
	new_argv[1] = "-C";
	for (i = 1; i < argc; i++)
	{
	    new_argv[i + 1] = argv[i];
	}
	new_argv[i + 1] = NULL;
	argc++;
	argv = new_argv;
    }
    while ((i = getopt(argc, argv, "C:s:t:d:U")) != EOF)
    {
	switch (i)
	{
	    case 'C':
		g_free(config);
		config = g_strdup(optarg);
		break;

	    case 's':
		g_free(server_name);
		server_name = g_strdup(optarg);
		break;

	    case 't':
		g_free(tape_server_name);
		tape_server_name = g_strdup(optarg);
		break;

	    case 'd':
		g_free(tape_device_name);
		tape_device_name = g_strdup(optarg);
		break;

	    case 'U':
	    case '?':
		(void)g_printf(USAGE);
		return 0;
	}
    }
    if (optind != argc)
    {
	(void)g_fprintf(stderr, USAGE);
	exit(1);
    }

    amfree(disk_name);
    amfree(mount_point);
    amfree(disk_path);
    dump_date[0] = '\0';

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    /* set up signal handler */
    act.sa_handler = sigint_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
#ifdef SA_RESTORER
    act.sa_restorer = NULL;
#endif
    if (sigaction(SIGINT, &act, &oact) != 0) {
	error(_("error setting signal handler: %s"), strerror(errno));
	/*NOTREACHED*/
    }

    service_name = "amandaidx";

    g_printf(_("AMRECOVER Version %s. Contacting server on %s ...\n"),
	   VERSION, server_name);
    if ((sp = getservbyname(service_name, "tcp")) == NULL) {
	error(_("%s/tcp unknown protocol"), service_name);
	/*NOTREACHED*/
    }
    server_socket = stream_client_privileged(server_name,
					     (in_port_t)ntohs((in_port_t)sp->s_port),
					     0,
					     0,
					     &my_port,
					     0);
    if (server_socket < 0) {
	error(_("cannot connect to %s: %s"), server_name, strerror(errno));
	/*NOTREACHED*/
    }
    if (my_port >= IPPORT_RESERVED) {
        aclose(server_socket);
	error(_("did not get a reserved port: %d"), my_port);
	/*NOTREACHED*/
    }

    /* get server's banner */
    if (grab_reply(1) == -1) {
        aclose(server_socket);
	exit(1);
    }
    if (!server_happy())
    {
	dbclose();
	aclose(server_socket);
	exit(1);
    }

    /* do the security thing */
    line = get_security();
    if (converse(line) == -1) {
        aclose(server_socket);
	exit(1);
    }
    if (!server_happy()) {
        aclose(server_socket);
	exit(1);
    }
    memset(line, '\0', strlen(line));
    amfree(line);

    /* try to get the features from the server */
    {
	char *our_feature_string = NULL;
	char *their_feature_string = NULL;

	our_features = am_init_feature_set();
	our_feature_string = am_feature_to_string(our_features);
	line = g_strconcat("FEATURES ", our_feature_string, NULL);
	if(exchange(line) == 0) {
	    their_feature_string = g_strdup(server_line+13);
	    indexsrv_features = am_string_to_feature(their_feature_string);
	}
	else {
	    indexsrv_features = am_set_default_feature_set();
        }
	amfree(our_feature_string);
	amfree(their_feature_string);
	amfree(line);
    }

    /* set the date of extraction to be today */
    (void)time(&timer);
    tm = localtime(&timer);
    if (tm)
	strftime(dump_date, sizeof(dump_date), "%Y-%m-%d", tm);
    else
	error(_("BAD DATE"));

    g_printf(_("Setting restore date to today (%s)\n"), dump_date);
    line = g_strconcat("DATE ", dump_date, NULL);
    if (converse(line) == -1) {
        aclose(server_socket);
	exit(1);
    }
    amfree(line);

    line = g_strconcat("SCNF ", config, NULL);
    if (converse(line) == -1) {
        aclose(server_socket);
	exit(1);
    }
    amfree(line);

    if (server_happy())
    {
	/* set host we are restoring to this host by default */
	amfree(dump_hostname);
	set_host(localhost);
	if (dump_hostname)
	{
            /* get a starting disk and directory based on where
	       we currently are */
	    switch (guess_disk(cwd, sizeof(cwd), &dn_guess, &mpt_guess))
	    {
		case 1:
		    /* okay, got a guess. Set disk accordingly */
		    g_printf(_("$CWD '%s' is on disk '%s' mounted at '%s'.\n"),
			   cwd, dn_guess, mpt_guess);
		    set_disk(dn_guess, mpt_guess);
		    set_directory(cwd);
		    if (server_happy() && !g_str_equal(cwd, mpt_guess))
		        g_printf(_("WARNING: not on root of selected filesystem, check man-page!\n"));
		    amfree(dn_guess);
		    amfree(mpt_guess);
		    break;

		case 0:
		    g_printf(_("$CWD '%s' is on a network mounted disk\n"),
			   cwd);
		    g_printf(_("so you must 'sethost' to the server\n"));
		    /* fake an unhappy server */
		    server_line[0] = '5';
		    break;

		case 2:
		case -1:
		default:
		    g_printf(_("Use the setdisk command to choose dump disk to recover\n"));
		    /* fake an unhappy server */
		    server_line[0] = '5';
		    break;
	    }
	}
    }

    quit_prog = 0;
    do
    {
	if ((lineread = readline("amrecover> ")) == NULL) {
	    clearerr(stdin);
	    putchar('\n');
	    break;
	}
	if (lineread[0] != '\0') 
	{
	    add_history(lineread);
	    process_line(lineread);	/* act on line's content */
	}
	amfree(lineread);
    } while (!quit_prog);

    dbclose();

    aclose(server_socket);
    return 0;
}
Esempio n. 9
0
static int _winbind_read_password(pam_handle_t * pamh
				  ,unsigned int ctrl
				  ,const char *comment
				  ,const char *prompt1
				  ,const char *prompt2
				  ,const char **pass)
{
	int authtok_flag;
	int retval;
	const char *item;
	char *token;

	/*
	 * make sure nothing inappropriate gets returned
	 */

	*pass = token = NULL;

	/*
	 * which authentication token are we getting?
	 */

	authtok_flag = on(WINBIND__OLD_PASSWORD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK;

	/*
	 * should we obtain the password from a PAM item ?
	 */

	if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) {
		retval = pam_get_item(pamh, authtok_flag, (const void **) &item);
		if (retval != PAM_SUCCESS) {
			/* very strange. */
			_pam_log(LOG_ALERT, 
				 "pam_get_item returned error to unix-read-password"
			    );
			return retval;
		} else if (item != NULL) {	/* we have a password! */
			*pass = item;
			item = NULL;
			return PAM_SUCCESS;
		} else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) {
			return PAM_AUTHTOK_RECOVER_ERR;		/* didn't work */
		} else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl)
			   && off(WINBIND__OLD_PASSWORD, ctrl)) {
			return PAM_AUTHTOK_RECOVER_ERR;
		}
	}
	/*
	 * getting here implies we will have to get the password from the
	 * user directly.
	 */

	{
		struct pam_message msg[3], *pmsg[3];
		struct pam_response *resp;
		int i, replies;

		/* prepare to converse */

		if (comment != NULL) {
			pmsg[0] = &msg[0];
			msg[0].msg_style = PAM_TEXT_INFO;
			msg[0].msg = comment;
			i = 1;
		} else {
			i = 0;
		}

		pmsg[i] = &msg[i];
		msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
		msg[i++].msg = prompt1;
		replies = 1;

		if (prompt2 != NULL) {
			pmsg[i] = &msg[i];
			msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
			msg[i++].msg = prompt2;
			++replies;
		}
		/* so call the conversation expecting i responses */
		resp = NULL;
		retval = converse(pamh, i, pmsg, &resp);

		if (resp != NULL) {

			/* interpret the response */

			if (retval == PAM_SUCCESS) {	/* a good conversation */

				token = x_strdup(resp[i - replies].resp);
				if (token != NULL) {
					if (replies == 2) {

						/* verify that password entered correctly */
						if (!resp[i - 1].resp
						    || strcmp(token, resp[i - 1].resp)) {
							_pam_delete(token);	/* mistyped */
							retval = PAM_AUTHTOK_RECOVER_ERR;
							_make_remark(pamh								    ,PAM_ERROR_MSG, MISTYPED_PASS);
						}
					}
				} else {
					_pam_log(LOG_NOTICE
						 ,"could not recover authentication token");
				}

			}
			/*
			 * tidy up the conversation (resp_retcode) is ignored
			 * -- what is it for anyway? AGM
			 */

			_pam_drop_reply(resp, i);

		} else {
			retval = (retval == PAM_SUCCESS)
			    ? PAM_AUTHTOK_RECOVER_ERR : retval;
		}
	}

	if (retval != PAM_SUCCESS) {
		if (on(WINBIND_DEBUG_ARG, ctrl))
			_pam_log(LOG_DEBUG,
			         "unable to obtain a password");
		return retval;
	}
	/* 'token' is the entered password */

	/* we store this password as an item */
	
	retval = pam_set_item(pamh, authtok_flag, token);
	_pam_delete(token);	/* clean it up */
	if (retval != PAM_SUCCESS
	    || (retval = pam_get_item(pamh, authtok_flag
				      ,(const void **) &item))
	    != PAM_SUCCESS) {
		
		_pam_log(LOG_CRIT, "error manipulating password");
		return retval;
		
	}

	*pass = item;
	item = NULL;		/* break link to password */

	return PAM_SUCCESS;
}
Esempio n. 10
0
void DrasculaEngine::doTalkSequenceCommand(TalkSequenceCommand cmd) {
	switch (cmd.commandType) {
	case kPause:
		pause(cmd.action);
		break;
	case kSetFlag:
		flags[cmd.action] = 1;
		break;
	case kClearFlag:
		flags[cmd.action] = 0;
		break;
	case kPickObject:
		pickObject(cmd.action);
		break;
	case kAddObject:
		addObject(cmd.action);
		break;
	case kBreakOut:
		breakOut = 1;
		break;
	case kConverse:
		converse(cmd.action);
		break;
	case kPlaceVB:
		placeVonBraun(cmd.action);
		break;
	case kUpdateRoom:
		updateRoom();
		break;
	case kUpdateScreen:
		updateScreen();
		break;
	case kTrackProtagonist:
		trackProtagonist = cmd.action;
		break;
	case kPlaySound:
		playSound(cmd.action);
		break;
	case kFinishSound:
		finishSound();
		break;
	case kTalkerGeneral:
		talk(cmd.action);
		break;
	case kTalkerDrunk:
		talk_drunk(cmd.action);
		break;
	case kTalkerPianist:
		talk_pianist(cmd.action);
		break;
	case kTalkerBJ:
		talk_bj(cmd.action);
		break;
	case kTalkerVBNormal:
		talk_vonBraun(cmd.action, kVonBraunNormal);
		break;
	case kTalkerVBDoor:
		talk_vonBraun(cmd.action, kVonBraunDoor);
		break;
	case kTalkerIgorSeated:
		talk_igor(cmd.action, kIgorSeated);
		break;
	case kTalkerWerewolf:
		talk_werewolf(cmd.action);
		break;
	case kTalkerMus:
		talk_mus(cmd.action);
		break;
	case kTalkerDrascula:
		talk_drascula(cmd.action, 1);
		break;
	case kTalkerBartender0:
		talk_bartender(cmd.action, 0);
		break;
	case kTalkerBartender1:
		talk_bartender(cmd.action, 1);
		break;
	default:
		error("doTalkSequenceCommand: Unknown command: %d", cmd.commandType);
	}
}
Esempio n. 11
0
PAM_EXTERN 
int pam_sm_chauthtok (pam_handle_t * pamh, int flags,
    int argc, const char **argv) {

    int ctrl, retval;
    char *user;
    char *pass;
    char *tty;
    char *r_addr;
    int srv_i;
    int tac_fd;
    int status = PAM_TRY_AGAIN;
    int seq = 0;

    user = pass = tty = r_addr = NULL;

    ctrl = _pam_parse (argc, argv);

    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)"
            , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT);

    /* Preliminary call to check readiness of our module */
    if (flags & PAM_PRELIM_CHECK) {
    	/* Can we connect to TACACS? */
    	for (srv_i = 0; srv_i < tac_srv_no; srv_i++) {
    		if (ctrl & PAM_TAC_DEBUG)
    			_pam_log (LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i );
    		tac_fd = tac_connect_single(tac_srv[srv_i], tac_srv_key[srv_i]);
			if (tac_fd < 0) {
				_pam_log (LOG_ERR, "connection failed srv %d: %m", srv_i);
				if (srv_i == tac_srv_no-1) {
					_pam_log (LOG_ERR, "no more servers to connect");
					return PAM_TRY_AGAIN;
				}
				continue;
			}
    	}
    	close(tac_fd);
    	return PAM_SUCCESS;
    }

    if ((user = _pam_get_user(pamh)) == NULL)
        return PAM_USER_UNKNOWN;

    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user);

    /* CHPASS does not send a password in data field,
     * user is prompted by a GETDATA reply packet
     */
    pass = malloc(5);
    strcpy(pass,"null");

    tty = _pam_get_terminal(pamh);
    if (!strncmp (tty, "/dev/", 5))
        tty += 5;
    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: tty [%s] obtained", __FUNCTION__, tty);

    r_addr = _pam_get_rhost(pamh);
    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: rhost [%s] obtained", __FUNCTION__, r_addr);

    /* Attempt server connect */
    for (srv_i = 0; srv_i < tac_srv_no; srv_i++) {
        status = TAC_PLUS_AUTHEN_STATUS_FAIL;
        if (ctrl & PAM_TAC_DEBUG)
            _pam_log (LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i );

        tac_fd = tac_connect_single(tac_srv[srv_i], tac_srv_key[srv_i]);
        if (tac_fd < 0) {
            _pam_log (LOG_ERR, "connection failed srv %d: %m", srv_i);
            if (srv_i == tac_srv_no-1) {
                _pam_log (LOG_ERR, "no more servers to connect");
                return PAM_AUTHINFO_UNAVAIL;
            }
            continue;
        }

        /* Send AUTHEN/START */
        if (tac_authen_send(tac_fd, user, pass, tty, r_addr, TAC_PLUS_AUTHEN_CHPASS, ctrl) < 0) {
            _pam_log (LOG_ERR, "error sending auth req to TACACS+ server");
            status = PAM_AUTHINFO_UNAVAIL;
        } else {
        	/* Read AUTHEN/REPLY and act on status */
			struct msg_status *msgstatus = malloc(sizeof(msg_status));

			do
			{
				tac_authen_read(msgstatus, tac_fd, ctrl, &seq);
				status = msgstatus->status;

				switch (status) {
					case TAC_PLUS_AUTHEN_STATUS_GETPASS:
						/* AUTHEN/CONT with password */
						if (ctrl & PAM_TAC_DEBUG)
							_pam_log (LOG_DEBUG, "%s: tac_cont_send called", __FUNCTION__);

						if (tac_cont_send(tac_fd, pass, ctrl, seq+1) < 0) {
							_pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
							status = PAM_AUTHINFO_UNAVAIL;
						}
					break;

					case TAC_PLUS_AUTHEN_STATUS_GETDATA: {
						/* Get data from user with pam conversation */
						struct pam_message msg;
						struct pam_response *resp = NULL;
						int retval;
						char *user_data = NULL;

						/* set up conversation call */
						msg.msg_style = PAM_PROMPT_ECHO_OFF;
						msg.msg = malloc(100);
						strcpy((char *)msg.msg,msgstatus->server_msg);

						if ((retval = converse (pamh, 1, &msg, &resp)) != PAM_SUCCESS) {
							status = PAM_AUTHINFO_UNAVAIL;
						} else {
							if (resp != NULL) {
								if (resp->resp == NULL && (ctrl & PAM_TAC_DEBUG))
									_pam_log (LOG_DEBUG, "pam_sm_authenticate: NULL given by user for GETDATA request");

								user_data = resp->resp;
								resp->resp = NULL;
							} else {
								if (ctrl & PAM_TAC_DEBUG) {
									_pam_log (LOG_DEBUG, "pam_sm_authenticate: no error reported");
									_pam_log (LOG_DEBUG, "getting data from user - NULL returned!?");
								}
								return PAM_CONV_ERR;
							}

							/* AUTHEN/CONT with data */
							if (ctrl & PAM_TAC_DEBUG)
								_pam_log (LOG_DEBUG, "%s: tac_cont_send called", __FUNCTION__);

							if (tac_cont_send(tac_fd, user_data, ctrl, seq+1) < 0) {
								_pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
								status = PAM_AUTHINFO_UNAVAIL;
							}
						}
						free(msg.msg);
					}
					break;

					case TAC_PLUS_AUTHEN_STATUS_GETUSER:
						/* AUTHEN/CONT with username */
						if (ctrl & PAM_TAC_DEBUG)
							_pam_log (LOG_DEBUG, "%s: tac_cont_send called", __FUNCTION__);

						if (tac_cont_send(tac_fd, user, ctrl, seq+1) < 0) {
							_pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
							status = PAM_AUTHINFO_UNAVAIL;
						}
					break;
				}
			} while ( 	(status == TAC_PLUS_AUTHEN_STATUS_GETDATA) ||
						(status == TAC_PLUS_AUTHEN_STATUS_GETPASS) ||
						(status == TAC_PLUS_AUTHEN_STATUS_GETUSER)		);

            if (status != TAC_PLUS_AUTHEN_STATUS_PASS) {
                _pam_log (LOG_ERR, "auth failed: %d", status);
                status = PAM_AUTHTOK_ERR;
            } else {
                /* OK, we got authenticated; save the server that
                   accepted us for pam_sm_acct_mgmt and exit the loop */
                status = PAM_SUCCESS;
                active_server = tac_srv[srv_i];
                active_key = tac_srv_key[srv_i];
                close(tac_fd);
                break;
            }
        }
        close(tac_fd);
    }

    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: exit with pam status: %i", __FUNCTION__, status);

    bzero (pass, strlen (pass));
    free(pass);
    pass = NULL;

    return status;
}    /* pam_sm_chauthtok */
Esempio n. 12
0
/* authenticates user on remote TACACS+ server
 * returns PAM_SUCCESS if the supplied username and password
 * pair is valid 
 */
PAM_EXTERN 
int pam_sm_authenticate (pam_handle_t * pamh, int flags,
    int argc, const char **argv) {

    int ctrl, retval;
    char *user;
    char *pass;
    char *tty;
    char *r_addr;
    int srv_i;
    int tac_fd;
    int status = PAM_AUTH_ERR;
    int seq = 0;

    user = pass = tty = r_addr = NULL;

    ctrl = _pam_parse (argc, argv);

    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)"
            , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT);

    if ((user = _pam_get_user(pamh)) == NULL)
        return PAM_USER_UNKNOWN;

    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user);
  
    /* uwzgledniac PAM_DISALLOW_NULL_AUTHTOK */

    retval = tacacs_get_password (pamh, flags, ctrl, &pass);

    if (retval != PAM_SUCCESS || pass == NULL || *pass == '\0') {
        _pam_log (LOG_ERR, "unable to obtain password");
        return PAM_CRED_INSUFFICIENT;
    }

    retval = pam_set_item (pamh, PAM_AUTHTOK, pass);
    if (retval != PAM_SUCCESS) {
        _pam_log (LOG_ERR, "unable to set password");
        return PAM_CRED_INSUFFICIENT;
    }

    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: password obtained", __FUNCTION__);

    tty = _pam_get_terminal(pamh);
    if (!strncmp (tty, "/dev/", 5))
        tty += 5;
    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: tty [%s] obtained", __FUNCTION__, tty);

    r_addr = _pam_get_rhost(pamh);
    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: rhost [%s] obtained", __FUNCTION__, r_addr);

    /* Attempt server connect */
    for (srv_i = 0; srv_i < tac_srv_no; srv_i++) {
        status = TAC_PLUS_AUTHEN_STATUS_FAIL;
        if (ctrl & PAM_TAC_DEBUG)
            _pam_log (LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i );

        tac_fd = tac_connect_single(tac_srv[srv_i], tac_srv_key[srv_i]);
        if (tac_fd < 0) {
            _pam_log (LOG_ERR, "connection failed srv %d: %m", srv_i);
            if (srv_i == tac_srv_no-1) {
                _pam_log (LOG_ERR, "no more servers to connect");
                return PAM_AUTHINFO_UNAVAIL;
            }
            continue;
        }

        /* Send AUTHEN/START */
        if (tac_authen_send(tac_fd, user, pass, tty, r_addr, TAC_PLUS_AUTHEN_LOGIN, ctrl) < 0) {
            _pam_log (LOG_ERR, "error sending auth req to TACACS+ server");
            status = PAM_AUTHINFO_UNAVAIL;
        } else {
        	/* Read AUTHEN/REPLY and act on status */
        	struct msg_status *msgstatus = malloc(sizeof(msg_status));

            do
			{
            	tac_authen_read(msgstatus, tac_fd, ctrl, &seq);
        		status = msgstatus->status;

            	switch (status) {
            		case TAC_PLUS_AUTHEN_STATUS_GETPASS:
            			/* AUTHEN/CONT with password */
						if (ctrl & PAM_TAC_DEBUG)
							_pam_log (LOG_DEBUG, "%s: tac_cont_send called", __FUNCTION__);

						if (tac_cont_send(tac_fd, pass, ctrl, seq+1) < 0) {
							_pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
							status = PAM_MAXTRIES;
						}
            		break;

            		case TAC_PLUS_AUTHEN_STATUS_GETDATA: {
            			/* The only GETDATA request should be if the user's password
            			 * has expired and ACS is requesting a new password
            			 *
            			 * Check if a conversation function has been set and either
            			 * return a PAM_AUTHTOK_EXPIRED or start a conversation
            			 * with the user for to change the password
            			 */
            			if (!strcmp(tty,"http")) {
            				status = PAM_NEW_AUTHTOK_REQD;
            				if (ctrl & PAM_TAC_DEBUG)
            					_pam_log (LOG_DEBUG, "%s: expired", __FUNCTION__);
            			} else {

							/* Get data from user with pam conversation */
							struct pam_message msg;
							struct pam_response *resp = NULL;
							int retval;
							char *user_data = NULL;

							/* set up conversation call */
							msg.msg_style = PAM_PROMPT_ECHO_OFF;
							msg.msg = malloc(100);
							strcpy((char *)msg.msg,msgstatus->server_msg);

							if ((retval = converse (pamh, 1, &msg, &resp)) != PAM_SUCCESS) {
								status = PAM_AUTHINFO_UNAVAIL;
							} else {
								if (resp != NULL) {
									if (resp->resp == NULL && (ctrl & PAM_TAC_DEBUG))
										_pam_log (LOG_DEBUG, "pam_sm_authenticate: NULL given by user for GETDATA request");

									user_data = resp->resp;
									resp->resp = NULL;
								} else {
									if (ctrl & PAM_TAC_DEBUG) {
										_pam_log (LOG_DEBUG, "pam_sm_authenticate: no error reported");
										_pam_log (LOG_DEBUG, "getting data from user - NULL returned!?");
									}
									return PAM_CONV_ERR;
								}

								/* AUTHEN/CONT with data */
								if (ctrl & PAM_TAC_DEBUG)
									_pam_log (LOG_DEBUG, "%s: tac_cont_send called", __FUNCTION__);

								if (tac_cont_send(tac_fd, user_data, ctrl, seq+1) < 0) {
									_pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
									status = PAM_AUTHINFO_UNAVAIL;
								}
							}
							free(msg.msg);
            			}
            		}
            		break;

            		case TAC_PLUS_AUTHEN_STATUS_GETUSER:
            			/* AUTHEN/CONT with username */
            			if (ctrl & PAM_TAC_DEBUG)
							_pam_log (LOG_DEBUG, "%s: tac_cont_send called", __FUNCTION__);

						if (tac_cont_send(tac_fd, user, ctrl, seq+1) < 0) {
							_pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
							status = PAM_AUTHINFO_UNAVAIL;
						}
            		break;
            	}
            } while ( 	(status == TAC_PLUS_AUTHEN_STATUS_GETDATA) ||
            			(status == TAC_PLUS_AUTHEN_STATUS_GETPASS) ||
            			(status == TAC_PLUS_AUTHEN_STATUS_GETUSER)		);

            if (ctrl & PAM_TAC_DEBUG)
            	_pam_log (LOG_DEBUG, "%s: out of while loop status=%d", __FUNCTION__,status);

            if (status == TAC_PLUS_AUTHEN_STATUS_PASS) {
            	/* OK, we got authenticated; save the server that
				   accepted us for pam_sm_acct_mgmt and exit the loop */
				status = PAM_SUCCESS;
				active_server = tac_srv[srv_i];
				active_key = tac_srv_key[srv_i];
            } else if (status != PAM_NEW_AUTHTOK_REQD) {
                _pam_log (LOG_ERR, "auth failed: %d", status);
                status = PAM_AUTH_ERR;
            }
        }
        close(tac_fd);

        /* TODO: Allow time for tac server to reply
         * TODO: Check if reply received before connecting to next server
         */
    }

    if (ctrl & PAM_TAC_DEBUG)
        _pam_log (LOG_DEBUG, "%s: exit with pam status: %i", __FUNCTION__, status);

    bzero (pass, strlen (pass));
    free(pass);
    pass = NULL;

    return status;
}    /* pam_sm_authenticate */
Esempio n. 13
0
/* PAM entry point for authentication verification */
int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc,
                        const char **argv)
{

  struct passwd *pw = NULL, pw_s;
  const char *user = NULL;

  cfg_t cfg_st;
  cfg_t *cfg = &cfg_st;
  char buffer[BUFSIZE];
  char *buf = NULL;
  char *authfile_dir;
  int authfile_dir_len;
  int pgu_ret, gpn_ret;
  int retval = PAM_IGNORE;
  device_t *devices = NULL;
  unsigned n_devices = 0;

  parse_cfg(flags, argc, argv, cfg);

  if (!cfg->origin) {
    if (!strcpy(buffer, DEFAULT_ORIGIN_PREFIX)) {
      DBG(("Unable to create origin string"));
      goto done;
    }

    if (gethostname
        (buffer + strlen(DEFAULT_ORIGIN_PREFIX),
         BUFSIZE - strlen(DEFAULT_ORIGIN_PREFIX)) == -1) {
      DBG(("Unable to get host name"));
      goto done;
    }
    DBG(("Origin not specified, using \"%s\"", buffer));
    cfg->origin = strdup(buffer);
  }

  if (!cfg->origin) {
    DBG(("Unable to allocate memory"));
    goto done;
  }

  if (!cfg->appid) {
    DBG(("Appid not specified, using the same value of origin (%s)",
         cfg->origin));
    cfg->appid = strdup(cfg->origin);
  }

  if (!cfg->appid) {
    DBG(("Unable to allocate memory"));
    goto done;
  }

  if (cfg->max_devs == 0) {
    DBG(("Maximum devices number not set. Using default (%d)", MAX_DEVS));
    cfg->max_devs = MAX_DEVS;
  }

  devices = malloc(sizeof(device_t) * cfg->max_devs);
  if (!devices) {
    DBG(("Unable to allocate memory"));
    return PAM_IGNORE;
  }

  pgu_ret = pam_get_user(pamh, &user, NULL);
  if (pgu_ret != PAM_SUCCESS || user == NULL) {
    DBG(("Unable to access user %s", user));
    free(devices);
    devices = NULL;
    return PAM_CONV_ERR;
  }

  DBG(("Requesting authentication for user %s", user));

  gpn_ret = getpwnam_r(user, &pw_s, buffer, sizeof(buffer), &pw);
  if (gpn_ret != 0 || pw == NULL || pw->pw_dir == NULL
      || pw->pw_dir[0] != '/') {
    DBG(("Unable to retrieve credentials for user %s, (%s)", user,
         strerror(errno)));
    retval = PAM_USER_UNKNOWN;
    goto done;
  }

  DBG(("Found user %s", user));
  DBG(("Home directory for %s is %s", user, pw->pw_dir));

  if (!cfg->auth_file) {
    buf = NULL;
    authfile_dir = secure_getenv(DEFAULT_AUTHFILE_DIR_VAR);
    if (!authfile_dir) {
      DBG(("Variable %s is not set. Using default value ($HOME/.config/)",
           DEFAULT_AUTHFILE_DIR_VAR));
      authfile_dir_len =
          strlen(pw->pw_dir) + strlen("/.config") +
          strlen(DEFAULT_AUTHFILE) + 1;
      buf = malloc(sizeof(char) * (authfile_dir_len));

      if (!buf) {
        DBG(("Unable to allocate memory"));
        retval = PAM_IGNORE;
        goto done;
      }

      strcpy(buf, pw->pw_dir);
      strcat(buf, "/.config");
      strcat(buf, DEFAULT_AUTHFILE);
    } else {
      DBG(("Variable %s set to %s", DEFAULT_AUTHFILE_DIR_VAR,
           authfile_dir));
      authfile_dir_len =
          strlen(authfile_dir) + strlen(DEFAULT_AUTHFILE) + 1;
      buf = malloc(sizeof(char) * (authfile_dir_len));

      if (!buf) {
        DBG(("Unable to allocate memory"));
        retval = PAM_IGNORE;
        goto done;
      }

      strcpy(buf, authfile_dir);
      strcat(buf, DEFAULT_AUTHFILE);
    }

    DBG(("Using default authentication file %s", buf));

    cfg->auth_file = strdup(buf);
    if (!cfg->auth_file) {
      DBG(("Unable to allocate memory"));
      retval = PAM_IGNORE;
      goto done;
    }

    free(buf);
    buf = NULL;
  } else {
    DBG(("Using authentication file %s", cfg->auth_file));
  }
  retval =
      get_devices_from_authfile(cfg->auth_file, user, cfg->max_devs,
                                cfg->debug, devices, &n_devices);
  if (retval != 1) {
    DBG(("Unable to get devices from file %s", cfg->auth_file));
    retval = PAM_AUTHINFO_UNAVAIL;
    goto done;
  }

  if (n_devices == 0) {
    if (cfg->nouserok) {
      DBG(("Found no devices but nouserok specified. Skipping authentication"));
      retval = PAM_SUCCESS;
      goto done;
    } else {
      DBG(("Found no devices. Aborting."));
      retval = PAM_AUTHINFO_UNAVAIL;
      goto done;
    }
  }

  if (cfg->manual == 0) {
    if (cfg->interactive) {
      converse(pamh, PAM_PROMPT_ECHO_ON,
               "Insert your U2F device, then press ENTER.\n");
    }

    retval = do_authentication(cfg, devices, n_devices, pamh);
  } else {
    retval = do_manual_authentication(cfg, devices, n_devices, pamh);
  }

  if (retval != 1) {
    DBG(("do_authentication returned %d", retval));
    retval = PAM_AUTH_ERR;
    goto done;
  }

  retval = PAM_SUCCESS;

done:
  free_devices(devices, n_devices);

  if (buf) {
    free(buf);
    buf = NULL;
  }

  if (cfg->alwaysok && retval != PAM_SUCCESS) {
    DBG(("alwaysok needed (otherwise return with %d)", retval));
    retval = PAM_SUCCESS;
  }
  DBG(("done. [%s]", pam_strerror(pamh, retval)));

  return retval;

}
Esempio n. 14
0
/* stolen from pam_stress */
int tacacs_get_password (pam_handle_t * pamh, int flags __Unused,
    int ctrl, char **password) {

    const void *pam_pass;
    char *pass = NULL;

    if (ctrl & PAM_TAC_DEBUG)
        syslog (LOG_DEBUG, "%s: called", __FUNCTION__);

    if ( (ctrl & (PAM_TAC_TRY_FIRST_PASS | PAM_TAC_USE_FIRST_PASS))
        && (pam_get_item(pamh, PAM_AUTHTOK, &pam_pass) == PAM_SUCCESS)
        && (pam_pass != NULL) ) {
         if ((pass = strdup(pam_pass)) == NULL)
              return PAM_BUF_ERR;
    } else if ((ctrl & PAM_TAC_USE_FIRST_PASS)) {
         _pam_log(LOG_WARNING, "no forwarded password");
         return PAM_PERM_DENIED;
    } else {
         struct pam_message msg;
         struct pam_response *resp = NULL;
         int retval;

         /* set up conversation call */
         msg.msg_style = PAM_PROMPT_ECHO_OFF;

         if (!tac_prompt[0]) {
             msg.msg = "Password: "******"pam_sm_authenticate: NULL authtok given");

             pass = resp->resp;    /* remember this! */
             resp->resp = NULL;

             free(resp);
             resp = NULL;
         } else {
             if (ctrl & PAM_TAC_DEBUG) {
               _pam_log (LOG_DEBUG, "pam_sm_authenticate: no error reported");
               _pam_log (LOG_DEBUG, "getting password, but NULL returned!?");
             }
             return PAM_CONV_ERR;
         }
    }

    /*
       FIXME *password can still turn out as NULL
       and it can't be free()d when it's NULL
    */
    *password = pass;       /* this *MUST* be free()'d by this module */

    if(ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: obtained password", __FUNCTION__);

    return PAM_SUCCESS;
}
Esempio n. 15
0
void
set_disk(
    char *	dsk,
    char *	mtpt)
{
    char *cmd = NULL;
    char *uqdsk;
    char *uqmtpt = NULL;

    if (is_extract_list_nonempty())
    {
	g_printf(_("Must clear extract list before changing disk\n"));
	return;
    }

    /* if mount point specified, check it is valid */
    if (mtpt != NULL) {
	uqmtpt = unquote_string(mtpt);
	if (*mtpt != '/') {
	    g_printf(_("Mount point \"%s\" invalid - must start with /\n"), uqmtpt);
	    amfree(uqmtpt);
	    return;
	}
    }

    clear_dir_list();
    uqdsk = unquote_string(dsk);
    cmd = g_strconcat("DISK ", uqdsk, NULL);
    if (converse(cmd) == -1)
	exit(1);
    amfree(cmd);

    if (!server_happy()) {
	amfree(uqdsk);
	amfree(uqmtpt);
	return;
    }

    g_free(disk_name);
    disk_name = g_strdup(uqdsk);
    if (mtpt == NULL)
    {
	/* mount point not specified */
	if (*uqdsk == '/')
	{
	    /* disk specified by mount point, hence use it */
	    g_free(mount_point);
	    mount_point = g_strdup(uqdsk);
	}
	else
	{
	    /* device name given, use '/' because nothing better */
	    g_free(mount_point);
	    mount_point = g_strdup("/");
	}
    }
    else
    {
	/* mount point specified */
	g_free(mount_point);
	mount_point = g_strdup(uqmtpt);
    }

    /* set the working directory to the mount point */
    /* there is the possibility that there are no index records for the
       disk for the given date, hence setting the directory to the
       mount point will fail. Preempt this by checking first so we can write
       a more informative message. */
    if (exchange("OISD /") == -1)
	exit(1);
    if (server_happy())
    {
	g_free(disk_path);
	disk_path = g_strdup("/");
	suck_dir_list_from_server();	/* get list of directory contents */
    }
    else
    {
	g_printf(_("No index records for disk for specified date\n"));
	g_printf(_("If date correct, notify system administrator\n"));
	g_free(disk_path);
	disk_path = g_strdup("/");	/* fake it */
	clear_dir_list();
    }
    amfree(uqmtpt);
    amfree(uqdsk);
}
Esempio n. 16
0
void
quit(void)
{
    quit_prog = 1;
    (void)converse("QUIT");
}
Esempio n. 17
0
void
set_host(
    const char *	host)
{
    char *cmd = NULL;
    struct hostent *hp;
    char **hostp;
    int found_host = 0;
    char *uqhost;

    if (is_extract_list_nonempty())
    {
	g_printf(_("Must clear extract list before changing host\n"));
	return;
    }

    uqhost = unquote_string(host);
    cmd = g_strconcat("HOST ", uqhost, NULL);
    if (converse(cmd) == -1)
	exit(1);
    if (server_happy())
    {
	found_host = 1;
    }
    else
    {
	/*
	 * Try converting the given host to a fully qualified name
	 * and then try each of the aliases.
	 */
	if ((hp = gethostbyname(uqhost)) != NULL) {
	    host = hp->h_name;
	    g_printf(_("Trying host %s ...\n"), host);
	    g_free(cmd);
	    cmd = g_strconcat("HOST ", host, NULL);
	    if (converse(cmd) == -1)
		exit(1);
	    if(server_happy())
	    {
		found_host = 1;
	    }
	    else
	    {
	        for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
	        {
		    g_printf(_("Trying host %s ...\n"), host);
		    g_free(cmd);
		    cmd = g_strconcat("HOST ", host, NULL);
		    if (converse(cmd) == -1)
		        exit(1);
		    if(server_happy())
		    {
		        found_host = 1;
		        break;
		    }
		}
	    }
	}
    }
    if(found_host)
    {
	g_free(dump_hostname);
	dump_hostname = g_strdup(host);
	amfree(disk_name);
	amfree(mount_point);
	amfree(disk_path);
	clear_dir_list();
    }
    amfree(cmd);
    amfree(uqhost);
}
Esempio n. 18
0
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
    int argc, const char **argv)
{
	params_t params;
	struct pam_response *resp;
	struct passwd *pw, fake_pw;
#ifdef HAVE_SHADOW
	struct spwd *spw;
#endif
	char *user, *oldpass, *newpass, *randompass;
	const char *reason;
	int ask_oldauthtok;
	int randomonly, enforce, retries_left, retry_wanted;
	int status;

	params = defaults;
	status = parse(&params, pamh, argc, argv);
	if (status != PAM_SUCCESS)
		return status;

	ask_oldauthtok = 0;
	if (flags & PAM_PRELIM_CHECK) {
		if (params.flags & F_ASK_OLDAUTHTOK_PRELIM)
			ask_oldauthtok = 1;
	} else
	if (flags & PAM_UPDATE_AUTHTOK) {
		if (params.flags & F_ASK_OLDAUTHTOK_UPDATE)
			ask_oldauthtok = 1;
	} else
		return PAM_SERVICE_ERR;

	if (ask_oldauthtok && getuid() != 0) {
		status = converse(pamh, PAM_PROMPT_ECHO_OFF,
		    PROMPT_OLDPASS, &resp);

		if (status == PAM_SUCCESS) {
			if (resp && resp->resp) {
				status = pam_set_item(pamh,
				    PAM_OLDAUTHTOK, resp->resp);
				_pam_drop_reply(resp, 1);
			} else
				status = PAM_AUTHTOK_RECOVERY_ERR;
		}

		if (status != PAM_SUCCESS)
			return status;
	}

	if (flags & PAM_PRELIM_CHECK)
		return status;

	status = pam_get_item(pamh, PAM_USER, (pam_item_t *)&user);
	if (status != PAM_SUCCESS)
		return status;

	status = pam_get_item(pamh, PAM_OLDAUTHTOK, (pam_item_t *)&oldpass);
	if (status != PAM_SUCCESS)
		return status;

	if (params.flags & F_NON_UNIX) {
		pw = &fake_pw;
		pw->pw_name = user;
		pw->pw_gecos = "";
	} else {
		pw = getpwnam(user);
		endpwent();
		if (!pw)
			return PAM_USER_UNKNOWN;
		if ((params.flags & F_CHECK_OLDAUTHTOK) && getuid() != 0) {
			if (!oldpass)
				status = PAM_AUTH_ERR;
			else
#ifdef HAVE_SHADOW
			if (!strcmp(pw->pw_passwd, "x")) {
				spw = getspnam(user);
				endspent();
				if (spw) {
					if (strcmp(crypt(oldpass, spw->sp_pwdp),
					    spw->sp_pwdp))
						status = PAM_AUTH_ERR;
					memset(spw->sp_pwdp, 0,
					    strlen(spw->sp_pwdp));
				} else
					status = PAM_AUTH_ERR;
			} else
#endif
			if (strcmp(crypt(oldpass, pw->pw_passwd),
			    pw->pw_passwd))
				status = PAM_AUTH_ERR;
		}
		memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
		if (status != PAM_SUCCESS)
			return status;
	}

	randomonly = params.qc.min[4] > params.qc.max;

	if (getuid() != 0)
		enforce = params.flags & F_ENFORCE_USERS;
	else
		enforce = params.flags & F_ENFORCE_ROOT;

	if (params.flags & F_USE_AUTHTOK) {
		status = pam_get_item(pamh, PAM_AUTHTOK,
		    (pam_item_t *)&newpass);
		if (status != PAM_SUCCESS)
			return status;
		if (!newpass || (check_max(&params, pamh, newpass) && enforce))
			return PAM_AUTHTOK_ERR;
		reason = _passwdqc_check(&params.qc, newpass, oldpass, pw);
		if (reason) {
			say(pamh, PAM_ERROR_MSG, MESSAGE_WEAKPASS, reason);
			if (enforce)
				status = PAM_AUTHTOK_ERR;
		}
		return status;
	}

	retries_left = params.retry;

retry:
	retry_wanted = 0;

	if (!randomonly &&
	    params.qc.passphrase_words && params.qc.min[2] <= params.qc.max)
		status = say(pamh, PAM_TEXT_INFO, MESSAGE_INTRO_BOTH);
	else
		status = say(pamh, PAM_TEXT_INFO, MESSAGE_INTRO_PASSWORD);
	if (status != PAM_SUCCESS)
		return status;

	if (!randomonly && params.qc.min[3] <= params.qc.min[4])
		status = say(pamh, PAM_TEXT_INFO, MESSAGE_EXPLAIN_PASSWORD_1,
		    params.qc.min[3] == 8 || params.qc.min[3] == 11 ? "n" : "",
		    params.qc.min[3]);
	else
	if (!randomonly)
		status = say(pamh, PAM_TEXT_INFO, MESSAGE_EXPLAIN_PASSWORD_2,
		    params.qc.min[3] == 8 || params.qc.min[3] == 11 ? "n" : "",
		    params.qc.min[3],
		    params.qc.min[4] == 8 || params.qc.min[4] == 11 ? "n" : "",
		    params.qc.min[4]);
	if (status != PAM_SUCCESS)
		return status;

	if (!randomonly &&
	    params.qc.passphrase_words &&
	    params.qc.min[2] <= params.qc.max) {
		status = say(pamh, PAM_TEXT_INFO, MESSAGE_EXPLAIN_PASSPHRASE,
		    params.qc.passphrase_words,
		    params.qc.min[2], params.qc.max);
		if (status != PAM_SUCCESS)
			return status;
	}

	randompass = _passwdqc_random(&params.qc);
	if (randompass) {
		status = say(pamh, PAM_TEXT_INFO, randomonly ?
		    MESSAGE_RANDOMONLY : MESSAGE_RANDOM, randompass);
		if (status != PAM_SUCCESS) {
			_pam_overwrite(randompass);
			randompass = NULL;
		}
	} else
	if (randomonly) {
		say(pamh, PAM_ERROR_MSG, getuid() != 0 ?
		    MESSAGE_MISCONFIGURED : MESSAGE_RANDOMFAILED);
		return PAM_AUTHTOK_ERR;
	}

	status = converse(pamh, PAM_PROMPT_ECHO_OFF, PROMPT_NEWPASS1, &resp);
	if (status == PAM_SUCCESS && (!resp || !resp->resp))
		status = PAM_AUTHTOK_ERR;

	if (status != PAM_SUCCESS) {
		if (randompass) _pam_overwrite(randompass);
		return status;
	}

	newpass = strdup(resp->resp);

	_pam_drop_reply(resp, 1);

	if (!newpass) {
		if (randompass) _pam_overwrite(randompass);
		return PAM_AUTHTOK_ERR;
	}

	if (check_max(&params, pamh, newpass) && enforce) {
		status = PAM_AUTHTOK_ERR;
		retry_wanted = 1;
	}

	reason = NULL;
	if (status == PAM_SUCCESS &&
	    (!randompass || !strstr(newpass, randompass)) &&
	    (randomonly ||
	    (reason = _passwdqc_check(&params.qc, newpass, oldpass, pw)))) {
		if (randomonly)
			say(pamh, PAM_ERROR_MSG, MESSAGE_NOTRANDOM);
		else
			say(pamh, PAM_ERROR_MSG, MESSAGE_WEAKPASS, reason);
		if (enforce) {
			status = PAM_AUTHTOK_ERR;
			retry_wanted = 1;
		}
	}

	if (status == PAM_SUCCESS)
		status = converse(pamh, PAM_PROMPT_ECHO_OFF,
		    PROMPT_NEWPASS2, &resp);
	if (status == PAM_SUCCESS) {
		if (resp && resp->resp) {
			if (strcmp(newpass, resp->resp)) {
				status = say(pamh,
				    PAM_ERROR_MSG, MESSAGE_MISTYPED);
				if (status == PAM_SUCCESS) {
					status = PAM_AUTHTOK_ERR;
					retry_wanted = 1;
				}
			}
			_pam_drop_reply(resp, 1);
		} else
			status = PAM_AUTHTOK_ERR;
	}

	if (status == PAM_SUCCESS)
		status = pam_set_item(pamh, PAM_AUTHTOK, newpass);

	if (randompass) _pam_overwrite(randompass);
	_pam_overwrite(newpass);
	free(newpass);

	if (retry_wanted && --retries_left > 0) {
		status = say(pamh, PAM_TEXT_INFO, MESSAGE_RETRY);
		if (status == PAM_SUCCESS)
			goto retry;
	}

	return status;
}
Esempio n. 19
0
int
main(
    int		argc,
    char **	argv)
{
    int i;
    time_t timer;
    char *lineread = NULL;
    struct sigaction act, oact;
    extern char *optarg;
    extern int optind;
    char *line = NULL;
    const security_driver_t *secdrv;
    char *req = NULL;
    int response_error;
    struct tm *tm;
    config_overrides_t *cfg_ovr;
    char *starting_hostname = NULL;

    /*
     * Configure program for internationalization:
     *   1) Only set the message locale for now.
     *   2) Set textdomain for all amanda related programs to "amanda"
     *      We don't want to be forced to support dozens of message catalogs.
     */  
    setlocale(LC_MESSAGES, "C");
    textdomain("amanda"); 

    safe_fd(-1, 0);

    set_pname("amrecover");

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    dbopen(DBG_SUBDIR_CLIENT);

    /* treat amrecover-specific command line options as the equivalent
     * -o command-line options to set configuration values */
    cfg_ovr = new_config_overrides(argc/2);

    /* If the first argument is not an option flag, then we assume
     * it is a configuration name to match the syntax of the other
     * Amanda utilities. */
    if (argc > 1 && argv[1][0] != '-') {
	add_config_override(cfg_ovr, "conf", argv[1]);

	/* remove that option from the command line */
	argv[1] = argv[0];
	argv++; argc--;
    }

    /* now parse regular command-line '-' options */
    while ((i = getopt(argc, argv, "o:C:s:t:d:Uh:")) != EOF) {
	switch (i) {
	    case 'C':
		add_config_override(cfg_ovr, "conf", optarg);
		break;

	    case 's':
		add_config_override(cfg_ovr, "index_server", optarg);
		break;

	    case 't':
		add_config_override(cfg_ovr, "tape_server", optarg);
		break;

	    case 'd':
		add_config_override(cfg_ovr, "tapedev", optarg);
		break;

	    case 'o':
		add_config_override_opt(cfg_ovr, optarg);
		break;

	    case 'h':
		starting_hostname = g_strdup(optarg);
		break;

	    case 'U':
	    case '?':
		(void)g_printf(USAGE);
		return 0;
	}
    }
    if (optind != argc) {
	(void)g_fprintf(stderr, USAGE);
	exit(1);
    }

    /* load the base client configuration */
    set_config_overrides(cfg_ovr);
    config_init(CONFIG_INIT_CLIENT, NULL);

    if (config_errors(NULL) >= CFGERR_WARNINGS) {
	config_print_errors();
	if (config_errors(NULL) >= CFGERR_ERRORS) {
	    g_critical(_("errors processing config file"));
	}
    }

    /* and now try to load the configuration named in that file */
    config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
		getconf_str(CNF_CONF));

    check_running_as(RUNNING_AS_ROOT);

    dbrename(get_config_name(), DBG_SUBDIR_CLIENT);

    our_features = am_init_feature_set();
    our_features_string = am_feature_to_string(our_features);

    if (!starting_hostname) {
	starting_hostname = g_malloc(MAX_HOSTNAME_LENGTH+1);
	if (gethostname(starting_hostname, MAX_HOSTNAME_LENGTH) != 0) {
	    error(_("cannot determine local host name\n"));
	    /*NOTREACHED*/
	}
	starting_hostname[MAX_HOSTNAME_LENGTH] = '\0';
    }

    server_name = NULL;
    if (getconf_seen(CNF_INDEX_SERVER) == -2) { /* command line argument */
	server_name = getconf_str(CNF_INDEX_SERVER);
    }
    if (!server_name) {
	server_name = getenv("AMANDA_SERVER");
	if (server_name) {
	    g_printf(_("Using index server from environment AMANDA_SERVER (%s)\n"), server_name);
	}
    }
    if (!server_name) {
	server_name = getconf_str(CNF_INDEX_SERVER);
    }
    if (!server_name) {
	error(_("No index server set"));
	/*NOTREACHED*/
    }
    server_name = g_strdup(server_name);

    tape_server_name = NULL;
    if (getconf_seen(CNF_TAPE_SERVER) == -2) { /* command line argument */
	tape_server_name = getconf_str(CNF_TAPE_SERVER);
    }
    if (!tape_server_name) {
	tape_server_name = getenv("AMANDA_TAPE_SERVER");
	if (!tape_server_name) {
	    tape_server_name = getenv("AMANDA_TAPESERVER");
	    if (tape_server_name) {
		g_printf(_("Using tape server from environment AMANDA_TAPESERVER (%s)\n"), tape_server_name);
	    }
	} else {
	    g_printf(_("Using tape server from environment AMANDA_TAPE_SERVER (%s)\n"), tape_server_name);
	}
    }
    if (!tape_server_name) {
	tape_server_name = getconf_str(CNF_TAPE_SERVER);
    }
    if (!tape_server_name) {
	error(_("No tape server set"));
	/*NOTREACHED*/
    }
    tape_server_name = g_strdup(tape_server_name);

    amfree(tape_device_name);
    tape_device_name = getconf_str(CNF_TAPEDEV);
    if (!tape_device_name ||
	strlen(tape_device_name) == 0 ||
	!getconf_seen(CNF_TAPEDEV)) {
	tape_device_name = NULL;
    } else {
	tape_device_name = g_strdup(tape_device_name);
    }

    authopt = g_strdup(getconf_str(CNF_AUTH));


    amfree(disk_name);
    amfree(mount_point);
    amfree(disk_path);
    dump_date[0] = '\0';

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    /* set up signal handler */
    act.sa_handler = sigint_handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (sigaction(SIGINT, &act, &oact) != 0) {
	error(_("error setting signal handler: %s"), strerror(errno));
	/*NOTREACHED*/
    }

    proplist = g_hash_table_new_full(g_str_hash, g_str_equal, &g_free, &free_property_t);

    protocol_init();

    /* We assume that amindexd support fe_amindexd_options_features */
    /*                             and fe_amindexd_options_auth     */
    /* We should send a noop to really know                         */
    req = g_strdup_printf("SERVICE amindexd\n"
		    "OPTIONS features=%s;auth=%s;\n",
		    our_features_string, authopt);

    secdrv = security_getdriver(authopt);
    if (secdrv == NULL) {
	error(_("no '%s' security driver available for host '%s'"),
	    authopt, server_name);
	/*NOTREACHED*/
    }

    protocol_sendreq(server_name, secdrv, generic_client_get_security_conf,
		     req, STARTUP_TIMEOUT, amindexd_response, &response_error);

    amfree(req);
    protocol_run();

    g_printf(_("AMRECOVER Version %s. Contacting server on %s ...\n"),
	   VERSION, server_name);

    if(response_error != 0) {
	g_fprintf(stderr,"%s\n",errstr);
	exit(1);
    }

    /* get server's banner */
    if (grab_reply(1) == -1) {
        aclose(server_socket);
	exit(1);
    }
    if (!server_happy()) {
	dbclose();
	aclose(server_socket);
	exit(1);
    }

    /* try to get the features from the server */
    {
	char *their_feature_string = NULL;

	indexsrv_features = NULL;

	line = g_strdup_printf("FEATURES %s", our_features_string);
	if(exchange(line) == 0) {
	    their_feature_string = g_strdup(server_line+13);
	    indexsrv_features = am_string_to_feature(their_feature_string);
	    if (!indexsrv_features)
		g_printf(_("Bad feature string from server: %s"), their_feature_string);
	}
	if (!indexsrv_features)
	    indexsrv_features = am_set_default_feature_set();

	amfree(their_feature_string);
	amfree(line);
    }

    /* set the date of extraction to be today */
    (void)time(&timer);
    tm = localtime(&timer);
    if (tm) 
	strftime(dump_date, sizeof(dump_date), "%Y-%m-%d", tm);
    else
	error(_("BAD DATE"));

    g_printf(_("Setting restore date to today (%s)\n"), dump_date);
    line = g_strdup_printf("DATE %s", dump_date);
    if (converse(line) == -1) {
        aclose(server_socket);
	exit(1);
    }
    amfree(line);

    line = g_strdup_printf("SCNF %s", get_config_name());
    if (converse(line) == -1) {
        aclose(server_socket);
	exit(1);
    }
    amfree(line);

    if (server_happy()) {
	/* set host we are restoring to this host by default */
	amfree(dump_hostname);
	set_host(starting_hostname);
	if (dump_hostname)
	    g_printf(_("Use the setdisk command to choose dump disk to recover\n"));
	else
	    g_printf(_("Use the sethost command to choose a host to recover\n"));

    }

    quit_prog = 0;
    do {
	if ((lineread = readline("amrecover> ")) == NULL) {
	    clearerr(stdin);
	    putchar('\n');
	    break;
	}
	if (lineread[0] != '\0') 
	{
	    add_history(lineread);
	    dbprintf(_("user command: '%s'\n"), lineread);
	    process_line(lineread);	/* act on line's content */
	}
	amfree(lineread);
    } while (!quit_prog);

    dbclose();

    aclose(server_socket);
    return 0;
}
Esempio n. 20
0
/* no-op function for future use */
PAM_EXTERN
int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
    int argc, const char **argv) {

    int ctrl, retval;
    char *user;
    char *pass;
    char *tty;
    char *r_addr;
    const void *pam_pass = NULL;
    int srv_i;
    int tac_fd, status, msg, communicating;

    user = pass = tty = r_addr = NULL;

    ctrl = _pam_parse(argc, argv);

    if (ctrl & PAM_TAC_DEBUG)
        syslog (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)"
            , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT);

    syslog(LOG_DEBUG, "%s(flags=%d, argc=%d)", __func__, flags, argc);

    // read config file
    _read_config(ctrl);

    if (   (pam_get_item(pamh, PAM_OLDAUTHTOK, &pam_pass) == PAM_SUCCESS)
        && (pam_pass != NULL) ) {
         if ((pass = strdup(pam_pass)) == NULL)
              return PAM_BUF_ERR;
    } else {
        pass = strdup("");
    }
    
    if ((user = _pam_get_user(pamh)) == NULL) {
        if(pass) {
                xfree(pass);
        }
        return PAM_USER_UNKNOWN;
    }
    
    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user);

    tty = _pam_get_terminal(pamh);
    if (!strncmp(tty, "/dev/", 5))
        tty += 5;
    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: tty [%s] obtained", __FUNCTION__, tty);

    r_addr = _pam_get_rhost(pamh);
    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: rhost [%s] obtained", __FUNCTION__, r_addr);

    if (PAM_SILENT == (flags & PAM_SILENT)) {
        status = PAM_AUTHTOK_ERR;
        goto finish;
    }

    status = PAM_TRY_AGAIN;
    for (srv_i = 0; srv_i < tac_srv_no; srv_i++) {
        if (ctrl & PAM_TAC_DEBUG)
            syslog(LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i );

        tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout);
        if (tac_fd < 0) {
            _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i);
            continue;
        }
        if (PAM_PRELIM_CHECK == (flags & PAM_PRELIM_CHECK)) {
            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                syslog(LOG_DEBUG, "%s: finishing PAM_PRELIM_CHECK with srv %d",
                       __FUNCTION__, srv_i);

            close(tac_fd);
            status = PAM_SUCCESS;
            goto finish;
        }

        if (tac_authen_send(tac_fd, user, "", tty, r_addr, TAC_PLUS_AUTHEN_CHPASS) < 0) {
            close(tac_fd);
            _pam_log(LOG_ERR, "error sending auth req to TACACS+ server");
            continue;
        }
        communicating = 1;
        while (communicating) {
            struct areply re = { .attr = NULL, .msg = NULL, status = 0, flags = 0 };
            struct pam_message conv_msg = { .msg_style = 0, .msg = NULL };
            struct pam_response *resp = NULL;

            msg = tac_authen_read(tac_fd, &re);

            if (NULL != re.msg) {
                conv_msg.msg = re.msg;
            }

            /* talk the protocol */
            switch (msg) {
                case TAC_PLUS_AUTHEN_STATUS_PASS:
                    /* success */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_PASS");

                    if (NULL != conv_msg.msg) {
                        int retval = -1;

                        conv_msg.msg_style = PAM_TEXT_INFO;
                        retval = converse(pamh, 1, &conv_msg, &resp);
                        if (PAM_SUCCESS == retval) {
                            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                                syslog(LOG_DEBUG, "send msg=\"%s\"", conv_msg.msg);
                        }
                        else {
                            _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d",
                                     __FUNCTION__, conv_msg.msg, retval);
                        }

                    }
                    status = PAM_SUCCESS;
                    communicating = 0;

                    if (active_server.addr != NULL)
                    {
                        xfree(active_server.addr);
                    }
                    active_server.addr = (struct addrinfo*)xcalloc(1, sizeof(struct addrinfo));
                    bcopy(tac_srv[srv_i].addr, active_server.addr, sizeof(struct addrinfo));
                    if (active_server.key != NULL)
                    {
                        xfree(active_server.key);
                    }
                    active_server.key = xstrdup(tac_srv[srv_i].key);

                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i);

                    break;

                case TAC_PLUS_AUTHEN_STATUS_FAIL:
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_FAIL");

                    if (NULL != conv_msg.msg) {
                        int retval = -1;

                        conv_msg.msg_style = PAM_ERROR_MSG;
                        retval = converse(pamh, 1, &conv_msg, &resp);
                        if (PAM_SUCCESS == retval) {
                            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                                syslog(LOG_DEBUG, "send msg=\"%s\"", conv_msg.msg);
                        }
                        else {
                            _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d",
                                     __FUNCTION__, conv_msg.msg, retval);
                        }

                    }
                    status = PAM_AUTHTOK_ERR;
                    communicating = 0;

                    _pam_log(LOG_ERR, "chauthtok failed: %d", msg);

                    break;

                case TAC_PLUS_AUTHEN_STATUS_GETDATA:
                    if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETDATA");

                    if (NULL != conv_msg.msg) {
                        int retval = -1;
                        int echo_off = (0x1 == (re.flags & 0x1));
                        
                        conv_msg.msg_style = echo_off ? PAM_PROMPT_ECHO_OFF : PAM_PROMPT_ECHO_ON;
                        retval = converse(pamh, 1, &conv_msg, &resp);
                        if (PAM_SUCCESS == retval) {
                            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG)) 
                                syslog(LOG_DEBUG, "sent msg=\"%s\", resp=\"%s\"",
                                       conv_msg.msg, resp->resp);

                            if (PAM_TAC_DEBUG == (ctrl & PAM_TAC_DEBUG))
                                syslog(LOG_DEBUG, "%s: calling tac_cont_send", __FUNCTION__);

                            if (0 > tac_cont_send_seq(tac_fd, resp->resp, re.seq_no + 1)) {
                                _pam_log(LOG_ERR, "error sending continue req to TACACS+ server");
                                communicating = 0;
                            }
                        }
                        else {
                            _pam_log(LOG_WARNING, "%s: error sending msg=\"%s\", retval=%d",
                                     __FUNCTION__, conv_msg.msg, retval);
                            communicating = 0;
                        }
                    }
                    else { 
                        syslog(LOG_ERR, "GETDATA response with no message, returning PAM_TRY_AGAIN");
                        communicating = 0;
                    }

                    break;

                case TAC_PLUS_AUTHEN_STATUS_GETUSER:
                    /* not implemented */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETUSER");

                    communicating = 0;
                    break;

                case TAC_PLUS_AUTHEN_STATUS_GETPASS:
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_GETPASS");

                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "%s: calling tac_cont_send", __FUNCTION__);

                    if (tac_cont_send(tac_fd, pass) < 0) {
                        _pam_log (LOG_ERR, "error sending continue req to TACACS+ server");
                        communicating = 0;
                        break;
                    }
                    /* continue the while loop; go read tac response */
                    break;

                case TAC_PLUS_AUTHEN_STATUS_RESTART:
                    /* try it again */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_RESTART");

                    /*
                     * not implemented
                     * WdJ: I *think* you can just do tac_authen_send(user, pass) again
                     *      but I'm not sure
                     */
                    communicating = 0;
                    break;

                case TAC_PLUS_AUTHEN_STATUS_ERROR:
                    /* server has problems */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_ERROR");

                    communicating = 0;
                    break;

                case TAC_PLUS_AUTHEN_STATUS_FOLLOW:
                    /* server tells to try a different server address */
                    /* not implemented */
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: TAC_PLUS_AUTHEN_STATUS_FOLLOW");

                    communicating = 0;
                    break;

                default:
                    if (msg < 0) {
                        /* connection error */
                        communicating = 0;
                        if (ctrl & PAM_TAC_DEBUG)
                            syslog(LOG_DEBUG, "error communicating with tacacs server");
                        break;
                    }

                    /* unknown response code */
                    communicating = 0;
                    if (ctrl & PAM_TAC_DEBUG)
                        syslog(LOG_DEBUG, "tacacs status: unknown response 0x%02x", msg);
            }

            if (NULL != resp) {
                xfree(resp->resp);
                xfree(resp);
            }

            xfree(re.msg);

        }    /* end while(communicating) */
        close(tac_fd);

        if (status == PAM_SUCCESS || status == PAM_AUTHTOK_ERR)
            break;
    }

finish:
    if (status != PAM_SUCCESS && status != PAM_AUTHTOK_ERR)
        _pam_log(LOG_ERR, "no more servers to connect");

    if (ctrl & PAM_TAC_DEBUG)
        syslog(LOG_DEBUG, "%s: exit with pam status: %d", __FUNCTION__, status);

    if (NULL != pass) {
        bzero(pass, strlen(pass));
        xfree(pass);
        pass = NULL;
    }

    return status;
}    /* pam_sm_chauthtok */
#endif


#ifdef PAM_STATIC
struct pam_module _pam_tacplus_modstruct {
    "pam_tacplus",
    pam_sm_authenticate,
    pam_sm_setcred,
    pam_sm_acct_mgmt,
    pam_sm_open_session,
    pam_sm_close_session,
#ifdef PAM_SM_PASSWORD
    pam_sm_chauthtok
#else
    NULL
#endif
};
Esempio n. 21
0
int do_authentication(const cfg_t *cfg, const device_t *devices,
                      const unsigned n_devs, pam_handle_t *pamh) {
  u2fs_ctx_t *ctx;
  u2fs_auth_res_t *auth_result;
  u2fs_rc s_rc;
  u2fh_rc h_rc;
  u2fh_devs *devs = NULL;
  char *response = NULL;
  char *buf;
  int retval = -2;
  int cued = 0;
  unsigned i = 0;
  unsigned max_index = 0;
  unsigned max_index_prev = 0;

  h_rc = u2fh_global_init(cfg->debug ? U2FH_DEBUG : 0);
  if (h_rc != U2FH_OK) {
    D(cfg->debug_file, "Unable to initialize libu2f-host: %s", u2fh_strerror(h_rc));
    return retval;
  }
  h_rc = u2fh_devs_init(&devs);
  if (h_rc != U2FH_OK) {
    D(cfg->debug_file, "Unable to initialize libu2f-host device handles: %s",
       u2fh_strerror(h_rc));
    return retval;
  }

  if ((h_rc = u2fh_devs_discover(devs, &max_index)) != U2FH_OK) {
    if (cfg->debug)
      D(cfg->debug_file, "Unable to discover device(s), %s", u2fh_strerror(h_rc));
    return retval;
  }
  max_index_prev = max_index;

  if (cfg->debug)
    D(cfg->debug_file, "Device max index is %u", max_index);

  s_rc = u2fs_global_init(cfg->debug ? U2FS_DEBUG : 0);
  if (s_rc != U2FS_OK) {
    D(cfg->debug_file, "Unable to initialize libu2f-server: %s", u2fs_strerror(s_rc));
    return retval;
  }
  s_rc = u2fs_init(&ctx);
  if (s_rc != U2FS_OK) {
    D(cfg->debug_file, "Unable to initialize libu2f-server context: %s", u2fs_strerror(s_rc));
    return retval;
  }

  if ((s_rc = u2fs_set_origin(ctx, cfg->origin)) != U2FS_OK) {
    if (cfg->debug)
      D(cfg->debug_file, "Unable to set origin: %s", u2fs_strerror(s_rc));
    return retval;
  }

  if ((s_rc = u2fs_set_appid(ctx, cfg->appid)) != U2FS_OK) {
    if (cfg->debug)
      D(cfg->debug_file, "Unable to set appid: %s", u2fs_strerror(s_rc));
    return retval;
  }

  if (cfg->nodetect && cfg->debug)
    D(cfg->debug_file, "nodetect option specified, suitable key detection will be skipped");

  i = 0;
  while (i < n_devs) {

    retval = -2;

    if (cfg->debug)
      D(cfg->debug_file, "Attempting authentication with device number %d", i + 1);

    if ((s_rc = u2fs_set_keyHandle(ctx, devices[i].keyHandle)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set keyHandle: %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_set_publicKey(ctx, devices[i].publicKey)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set publicKey %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_authentication_challenge(ctx, &buf)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to produce authentication challenge: %s",
           u2fs_strerror(s_rc));
      free(buf);
      buf = NULL;
      return retval;
    }

    if (cfg->debug)
      D(cfg->debug_file, "Challenge: %s", buf);

    if (cfg->nodetect || (h_rc = u2fh_authenticate(devs, buf, cfg->origin, &response, 0)) == U2FH_OK ) {

      if (cfg->manual == 0 && cfg->cue && !cued) {
        cued = 1;
        converse(pamh, PAM_TEXT_INFO, DEFAULT_CUE);
      }

      retval = -1;

      if ((h_rc = u2fh_authenticate(devs, buf, cfg->origin, &response, U2FH_REQUEST_USER_PRESENCE)) ==
          U2FH_OK) {
        if (cfg->debug)
          D(cfg->debug_file, "Response: %s", response);

        s_rc = u2fs_authentication_verify(ctx, response, &auth_result);
        u2fs_free_auth_res(auth_result);
        free(response);
        response = NULL;
        if (s_rc == U2FS_OK) {
          retval = 1;

          free(buf);
          buf = NULL;
          break;
        }
      } else {
        if (cfg->debug)
          D(cfg->debug_file, "Unable to communicate to the device, %s", u2fh_strerror(h_rc));
      }
    } else {
      if (cfg->debug)
        D(cfg->debug_file, "Device for this keyhandle is not present.");
    }
    free(buf);
    buf = NULL;

    i++;

    if (u2fh_devs_discover(devs, &max_index) != U2FH_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to discover devices");
      return retval;
    }

    if (max_index > max_index_prev) {
      if (cfg->debug)
        D(cfg->debug_file, "Devices max_index has changed: %u (was %u). Starting over",
           max_index, max_index_prev);
      max_index_prev = max_index;
      i = 0;
    }
  }

  u2fh_devs_done(devs);
  u2fh_global_done();

  u2fs_done(ctx);
  u2fs_global_done();

  return retval;
}