예제 #1
0
/* this function sends a packet do TACACS+ server, asking
 * for validation of given username and password
 *
 * return value:
 *      0 : success
 *   <  0 : error status code, see LIBTAC_STATUS_...
 *             LIBTAC_STATUS_WRITE_ERR
 *             LIBTAC_STATUS_WRITE_TIMEOUT
 *             LIBTAC_STATUS_ASSEMBLY_ERR
 */
int tac_authen_send(int fd, const char *user, const char *pass, const char *tty,
		const char *r_addr, u_char action) {

	HDR *th; /* TACACS+ packet header */
	struct authen_start tb; /* message body */
	int user_len, pass_len, port_len, chal_len, token_len, bodylength, w;
	int r_addr_len;
	int pkt_len = 0;
	int ret = 0;
	char *chal = "1234123412341234";
	char *token = NULL;
	u_char *pkt = NULL;
	const uint8_t id = 5;

	th = _tac_req_header(TAC_PLUS_AUTHEN, 0);

	/* set some header options */
	if (!strcmp(tac_login, "login")) {
		th->version = TAC_PLUS_VER_0;
	} else {
		th->version = TAC_PLUS_VER_1;
	}
	th->encryption =
			tac_encryption ?
					TAC_PLUS_ENCRYPTED_FLAG : TAC_PLUS_UNENCRYPTED_FLAG;

	TACDEBUG(LOG_DEBUG, "%s: user '%s', tty '%s', rem_addr '%s', encrypt: %s",
					__FUNCTION__, user, tty, r_addr,
					(tac_encryption) ? "yes" : "no");

	/* get size of submitted data */
	user_len = strlen(user);
	chal_len = strlen(chal);
	pass_len = strlen(pass);
	port_len = strlen(tty);
	r_addr_len = strlen(r_addr);

	if (!strcmp(tac_login, "chap")) {
		u_char digest[MD5_LBLOCK];

		digest_chap(digest, id, pass, pass_len, chal, chal_len);

		token_len = sizeof(id) + chal_len + sizeof(digest);
		token = xcalloc(1, token_len);
		token[0] = id;
		memcpy(token + sizeof(id), chal, chal_len);
		memcpy(token + sizeof(id) + chal_len, digest, sizeof(digest));
	} else {
		token = xstrdup(pass);
		token_len = strlen(token);
	}

	/* fill the body of message */
	tb.action = action;
	tb.priv_lvl = tac_priv_lvl;
	if (!*tac_login) {
		/* default to PAP */
		tb.authen_type =
				TAC_PLUS_AUTHEN_CHPASS == action ?
						TAC_PLUS_AUTHEN_TYPE_ASCII : TAC_PLUS_AUTHEN_TYPE_PAP;
	} else {
		if (!strcmp(tac_login, "chap")) {
			tb.authen_type = TAC_PLUS_AUTHEN_TYPE_CHAP;
		} else if (!strcmp(tac_login, "login")) {
			tb.authen_type = TAC_PLUS_AUTHEN_TYPE_ASCII;
		} else {
			tb.authen_type = TAC_PLUS_AUTHEN_TYPE_PAP;
		}
	}
	tb.service = tac_authen_service;
	tb.user_len = user_len;
	tb.port_len = port_len;
	tb.r_addr_len = r_addr_len; /* may be e.g Caller-ID in future */
	tb.data_len = token_len;

	/* fill body length in header */
	bodylength = sizeof(tb) + user_len + port_len + r_addr_len + token_len;

	th->datalength = htonl(bodylength);

	/* we can now write the header */
	w = write(fd, th, TAC_PLUS_HDR_SIZE);
	if (w < 0 || w < TAC_PLUS_HDR_SIZE) {
		TACSYSLOG(
				LOG_ERR, "%s: short write on header, wrote %d of %d: %m", __FUNCTION__, w, TAC_PLUS_HDR_SIZE);
		free(token);
		free(pkt);
		free(th);
		return LIBTAC_STATUS_WRITE_ERR;
	}

	/* build the packet */
	pkt = (u_char *) xcalloc(1, bodylength + 10);

	bcopy(&tb, pkt + pkt_len, sizeof(tb)); /* packet body beginning */
	pkt_len += sizeof(tb);
	bcopy(user, pkt + pkt_len, user_len); /* user */
	pkt_len += user_len;
	bcopy(tty, pkt + pkt_len, port_len); /* tty */
	pkt_len += port_len;
	bcopy(r_addr, pkt + pkt_len, r_addr_len); /* rem addr */
	pkt_len += r_addr_len;

	bcopy(token, pkt + pkt_len, token_len); /* password */
	pkt_len += token_len;

	/* pkt_len == bodylength ? */
	if (pkt_len != bodylength) {
		TACSYSLOG(
				LOG_ERR, "%s: bodylength %d != pkt_len %d", __FUNCTION__, bodylength, pkt_len);
		free(token);
		free(pkt);
		free(th);
		return LIBTAC_STATUS_ASSEMBLY_ERR;
	}

	/* encrypt the body */
	_tac_crypt(pkt, th);

	w = write(fd, pkt, pkt_len);
	if (w < 0 || w < pkt_len) {
		TACSYSLOG(
				LOG_ERR, "%s: short write on body, wrote %d of %d: %m", __FUNCTION__, w, pkt_len);
		ret = LIBTAC_STATUS_WRITE_ERR;
	}

	free(token);
	free(pkt);
	free(th);
	TACDEBUG(LOG_DEBUG, "%s: exit status=%d", __FUNCTION__, ret);
	return ret;
} /* tac_authen_send */
예제 #2
0
/*
 * return value:
 *      0 : success
 *   <  0 : error status code, see LIBTAC_STATUS_...
 *             LIBTAC_STATUS_WRITE_ERR
 *             LIBTAC_STATUS_WRITE_TIMEOUT  (pending impl)
 *             LIBTAC_STATUS_ASSEMBLY_ERR   (pending impl)
 */
int tac_acct_send(int fd, int type, const char *user, char *tty,
    char *r_addr, struct tac_attrib *attr) {

    HDR *th;
    struct acct tb;
    u_char user_len, port_len, r_addr_len;
    struct tac_attrib *a;
    int i = 0;    /* arg count */
    int pkt_len = 0;
    int pktl = 0;
    int w;    /* write count */
    u_char *pkt=NULL;
    /* u_char *pktp; */             /* obsolute */
    int ret = 0;

    th = _tac_req_header(TAC_PLUS_ACCT, 0);

    /* set header options */
    th->version=TAC_PLUS_VER_0;
    th->encryption=tac_encryption ? TAC_PLUS_ENCRYPTED_FLAG : TAC_PLUS_UNENCRYPTED_FLAG;

    TACDEBUG(LOG_DEBUG, "%s: user '%s', tty '%s', rem_addr '%s', encrypt: %s, type: %s", \
        __FUNCTION__, user, tty, r_addr, \
        (tac_encryption) ? "yes" : "no", \
        tac_acct_flag2str(type));
        
    user_len=(u_char) strlen(user);
    port_len=(u_char) strlen(tty);
    r_addr_len=(u_char) strlen(r_addr);

    tb.flags=(u_char) type;
    tb.authen_method=tac_authen_method;
    tb.priv_lvl=tac_priv_lvl;
    if (!*tac_login) {
        /* default to PAP */
        tb.authen_type = TAC_PLUS_AUTHEN_TYPE_PAP;
    } else {
        if (strcmp(tac_login,"chap") == 0) {
            tb.authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP;
        } else if(strcmp(tac_login,"login") == 0) {
            tb.authen_type=TAC_PLUS_AUTHEN_TYPE_ASCII;
        } else {
            tb.authen_type=TAC_PLUS_AUTHEN_TYPE_PAP;
        }
    }
    tb.authen_service=tac_authen_service;
    tb.user_len=user_len;
    tb.port_len=port_len;
    tb.r_addr_len=r_addr_len;

    /* allocate packet */
    pkt=(u_char *) xcalloc(1, TAC_ACCT_REQ_FIXED_FIELDS_SIZE);
    pkt_len=sizeof(tb);

    /* fill attribute length fields */
    a = attr;
    while (a) {
        pktl = pkt_len;
        pkt_len += sizeof(a->attr_len);
        pkt = (u_char*) xrealloc(pkt, pkt_len);

        /* see comments in author_s.c
        pktp=pkt + pkt_len;
        pkt_len += sizeof(a->attr_len);
        pkt = xrealloc(pkt, pkt_len);   
        */

        bcopy(&a->attr_len, pkt + pktl, sizeof(a->attr_len));
        i++;

        a = a->next;
    }

    /* fill the arg count field and add the fixed fields to packet */
    tb.arg_cnt = i;
    bcopy(&tb, pkt, TAC_ACCT_REQ_FIXED_FIELDS_SIZE);

    /*
#define PUTATTR(data, len) \
        pktp = pkt + pkt_len; \
        pkt_len += len; \
        pkt = xrealloc(pkt, pkt_len); \
        bcopy(data, pktp, len);
    */
#define PUTATTR(data, len) \
    pktl = pkt_len; \
    pkt_len += len; \
    pkt = (u_char*) xrealloc(pkt, pkt_len); \
    bcopy(data, pkt + pktl, len);

    /* fill user and port fields */
    PUTATTR(user, user_len)
    PUTATTR(tty, port_len)
    PUTATTR(r_addr, r_addr_len)

    /* fill attributes */
    a = attr;
    while(a) {
        PUTATTR(a->attr, a->attr_len)
        a = a->next;
    }

    /* finished building packet, fill len_from_header in header */
    th->datalength = htonl(pkt_len);

    /* write header */
    w = write(fd, th, TAC_PLUS_HDR_SIZE);

    if(w < TAC_PLUS_HDR_SIZE) {
        TACSYSLOG(LOG_ERR, "%s: short write on header, wrote %d of %d: %m",\
            __FUNCTION__, w, TAC_PLUS_HDR_SIZE);
        free(pkt);
        free(th);
        return LIBTAC_STATUS_WRITE_ERR;
    }
        
    /* encrypt packet body  */
    _tac_crypt(pkt, th);

    /* write body */
    w=write(fd, pkt, pkt_len);
    if(w < pkt_len) {
        TACSYSLOG(LOG_ERR, "%s: short write on body, wrote %d of %d: %m",\
            __FUNCTION__, w, pkt_len);
        ret = LIBTAC_STATUS_WRITE_ERR;
    }

    free(pkt);
    free(th);
    TACDEBUG(LOG_DEBUG, "%s: exit status=%d", __FUNCTION__, ret);
    return ret;
}
예제 #3
0
파일: authen_s.c 프로젝트: WEMS/pam_tacplus
/* this function sends a packet do TACACS+ server, asking
 * for validation of given username and password
 *
 * return value:
 *      0 : success
 *   <  0 : error status code, see LIBTAC_STATUS_...
 *             LIBTAC_STATUS_WRITE_ERR
 *             LIBTAC_STATUS_WRITE_TIMEOUT
 *             LIBTAC_STATUS_ASSEMBLY_ERR
 */
int tac_authen_send(int fd, const char *user, char *pass, char *tty,
    char *r_addr, int action, int ctrl) {

    HDR *th;    /* TACACS+ packet header */
    struct authen_start tb;     /* message body */
    int user_len, port_len, chal_len, mdp_len, token_len, bodylength, w;
    int r_addr_len;
    int pkt_len = 0;
    int ret = 0;
    char *chal = "1234123412341234";
    char digest[MD5_LEN];
    char *token = NULL;
    u_char *pkt = NULL, *mdp = NULL;
    MD5_CTX mdcontext;

    th=_tac_req_header(TAC_PLUS_AUTHEN, 0);

    /* set some header options */
    if ((tac_login != NULL) && (strcmp(tac_login,"login") == 0)) {
        th->version = TAC_PLUS_VER_0;
    } else {
        th->version = TAC_PLUS_VER_1;
    }
    th->encryption = tac_encryption ? TAC_PLUS_ENCRYPTED_FLAG : TAC_PLUS_UNENCRYPTED_FLAG;

    if (ctrl & PAM_TAC_DEBUG)
    	TACDEBUG((LOG_DEBUG, "%s: user '%s', tty '%s', rem_addr '%s', encrypt: %s", \
			__FUNCTION__, user, tty, r_addr, \
			(tac_encryption) ? "yes" : "no"))
        
    if ((tac_login != NULL) && (strcmp(tac_login,"chap") == 0)) {
        chal_len = strlen(chal);
        mdp_len = sizeof(u_char) + strlen(pass) + chal_len;
        mdp = (u_char *) xcalloc(1, mdp_len);
        mdp[0] = 5;
        memcpy(&mdp[1], pass, strlen(pass));
        memcpy(mdp + strlen(pass) + 1, chal, chal_len);
        MD5Init(&mdcontext);
        MD5Update(&mdcontext, mdp, mdp_len);
        MD5Final((u_char *) digest, &mdcontext);
        free(mdp);
        token = (char*) xcalloc(1, sizeof(u_char) + 1 + chal_len + MD5_LEN);
        token[0] = 5;
        memcpy(&token[1], chal, chal_len);
        memcpy(token + chal_len + 1, digest, MD5_LEN);
    } else {
        token = xstrdup(pass);
    }

    /* get size of submitted data */
    user_len = strlen(user);
    port_len = strlen(tty);
    r_addr_len = strlen(r_addr);
    token_len = strlen(token);

    /* fill the body of message */
    tb.action = action;
    tb.priv_lvl = tac_priv_lvl;
    if (tac_login == NULL) {
        /* default to PAP */
        tb.authen_type = TAC_PLUS_AUTHEN_TYPE_PAP;
    } else {
        if (strcmp(tac_login,"chap") == 0) {
            tb.authen_type = TAC_PLUS_AUTHEN_TYPE_CHAP;
        } else if (strcmp(tac_login,"login") == 0) {
            tb.authen_type = TAC_PLUS_AUTHEN_TYPE_ASCII;
        } else {
            tb.authen_type = TAC_PLUS_AUTHEN_TYPE_PAP;
        }
    }
    tb.service = tac_authen_service;
    tb.user_len = user_len;
    tb.port_len = port_len;
    tb.r_addr_len = r_addr_len;    /* may be e.g Caller-ID in future */
    tb.data_len = token_len;

    /* fill body length in header */
    bodylength = sizeof(tb) + user_len
        + port_len + r_addr_len + token_len;

    th->datalength = htonl(bodylength);

    /* we can now write the header */
    w = write(fd, th, TAC_PLUS_HDR_SIZE);
    if (w < 0 || w < TAC_PLUS_HDR_SIZE) {
        TACSYSLOG((LOG_ERR,\
            "%s: short write on header, wrote %d of %d: %m",\
            __FUNCTION__, w, TAC_PLUS_HDR_SIZE))
        free(token);
        free(pkt);
        free(th);
        return LIBTAC_STATUS_WRITE_ERR;
    }

    /* build the packet */
    pkt = (u_char *) xcalloc(1, bodylength+10);

    bcopy(&tb, pkt+pkt_len, sizeof(tb)); /* packet body beginning */
    pkt_len += sizeof(tb);
    bcopy(user, pkt+pkt_len, user_len);  /* user */
    pkt_len += user_len;
    bcopy(tty, pkt+pkt_len, port_len);   /* tty */
    pkt_len += port_len;
    bcopy(r_addr, pkt+pkt_len, r_addr_len);   /* rem addr */
    pkt_len += r_addr_len;

    bcopy(token, pkt+pkt_len, token_len);  /* password */
    pkt_len += token_len;

    /* pkt_len == bodylength ? */
    if (pkt_len != bodylength) {
        TACSYSLOG((LOG_ERR, "%s: bodylength %d != pkt_len %d",\
            __FUNCTION__, bodylength, pkt_len))
        free(token);
        free(pkt);
        free(th);
        return LIBTAC_STATUS_ASSEMBLY_ERR;
    } 
        
    /* encrypt the body */
    _tac_crypt(pkt, th, bodylength);

    w = write(fd, pkt, pkt_len);
    if (w < 0 || w < pkt_len) {
        TACSYSLOG((LOG_ERR,\
            "%s: short write on body, wrote %d of %d: %m",\
            __FUNCTION__, w, pkt_len))
        ret = LIBTAC_STATUS_WRITE_ERR;
    }

    /* Packet Debug (In 'debug tacacs packet' format */
    if (ctrl & PAM_TAC_PACKET_DEBUG) {
		char *action_str;
		char *type_str;
		char *service_str;

		authen_action_string(&action_str, tb.action);
		authen_type_string(&type_str, tb.authen_type);
		authen_service_string(&service_str, tb.service);

		TACDEBUG((LOG_DEBUG, "T+: Version %u (0x%02X), type %u, seq %u, encryption %u",
				th->version, th->version, th->type, th->seq_no, th->encryption))
		TACDEBUG((LOG_DEBUG, "T+: session_id %u (0x%08X), dlen %u (0x%02X)",
				th->session_id, th->session_id, th->datalength, th->datalength))
		TACDEBUG((LOG_DEBUG, "T+: type:AUTHEN/START, priv_lvl:%u action:%s %s",
				tb.priv_lvl, action_str, type_str))
		TACDEBUG((LOG_DEBUG, "T+: svc:%s user_len:%u port_len:%u (0x%02X) raddr_len:%u (0x%02X) data_len:%d",
				service_str, tb.user_len, tb.port_len, tb.port_len, tb.r_addr_len,
				tb.r_addr_len, tb.data_len))
		TACDEBUG((LOG_DEBUG, "T+: user:  %s", user))
		TACDEBUG((LOG_DEBUG, "T+: port:  %s", tty))
		TACDEBUG((LOG_DEBUG, "T+: rem_addr:  %s", r_addr))
		/*TACDEBUG((LOG_DEBUG, "T+: data:  %s", token)) hide user password (!)*/
		TACDEBUG((LOG_DEBUG, "T+: data:  <hidden>"))
		TACDEBUG((LOG_DEBUG, "T+: End Packet"))

	    free(action_str);
	    free(type_str);
	    free(service_str);
    }

    free(token);
    free(pkt);
    free(th);

    if (ctrl & PAM_TAC_DEBUG)
    	TACDEBUG((LOG_DEBUG, "%s: exit status=%d", __FUNCTION__, ret))
    return ret;
}    /* tac_authen_send */
예제 #4
0
int
tac_account_read(tacacs_conf_t *conf, tacacs_server_t *server,
		 const char **ret_err_msg)
{
        int err = 0;
	HDR th;
	struct acct_reply *tb = NULL;
	int len_from_header, r, len_from_body;
	const char *msg = NULL;
	int msg_len, data_len;

	if (ret_err_msg == NULL) {
	    syslog(LOG_ERR, "%s: error no err msg buffer provided",
		   __FUNCTION__);
	    err = -1;
	    goto bail;
	}
	*ret_err_msg = NULL;

	if (server == NULL) {
	    syslog(LOG_ERR, "%s: error no TACACS+ server specified",
		   __FUNCTION__);
	    err = -1;
	    *ret_err_msg = no_server_err_msg;
	    goto bail;
	}

	reset_server(server, FALSE);

	r=read(conf->sockfd, &th, TAC_PLUS_HDR_SIZE);
	if(r < TAC_PLUS_HDR_SIZE) {
  		syslog(LOG_ERR,
 			"%s: short acct header, %d of %d: %m", __FUNCTION__,
		 	r, TAC_PLUS_HDR_SIZE);
		err = -1;
		*ret_err_msg = r == 0 ? "No response from server" :
                                        "Truncated response from server";
		goto bail;
 	}

 	/* check the reply fields in header */
	err = _tac_check_header(&th, TAC_PLUS_ACCT, server, &msg);
	if (err) {
            *ret_err_msg = msg;
	    goto bail;
	}

 	len_from_header=ntohl(th.datalength);
 	tb=(struct acct_reply *) xcalloc(1, len_from_header);

 	/* read reply packet body */
 	r=read(conf->sockfd, tb, len_from_header);
 	if(r < len_from_header) {
  		syslog(LOG_ERR,
			 "%s: incomplete message body, %d bytes, expected %d: %m",
			 __FUNCTION__,
			 r, len_from_header);
		err = -1;
		*ret_err_msg = r == 0 ? "Empty response message from server" :
                                        "Incomplete response message from server";
		goto bail;
 	}

 	/* decrypt the body */
 	_tac_crypt(server->secret, (u_char *) tb, &th, len_from_header);

	msg_len = tb->msg_len;
	data_len = tb->data_len;

 	/* check the length fields */
 	len_from_body=sizeof(tb->msg_len) + sizeof(tb->data_len) +
            sizeof(tb->status) + msg_len + data_len;

 	if(len_from_header != len_from_body) {
  		syslog(LOG_ERR,
			"%s: invalid reply content, incorrect key?",
			__FUNCTION__);
		err = -1;
		*ret_err_msg = system_err_msg;
		goto bail;
 	}

 	/* save status and clean up */
 	r=tb->status;
	if(msg_len) {
	    server->server_msg=(char *) xcalloc(1, msg_len);
	    bcopy(tb+TAC_ACCT_REPLY_FIXED_FIELDS_SIZE, server->server_msg,
		  msg_len); 
	    *ret_err_msg = server->server_msg;
	}

 	/* server logged our request successfully */
	if(r == TAC_PLUS_ACCT_STATUS_SUCCESS) {
	    TACDEBUG((LOG_DEBUG, "%s: accounted ok", __FUNCTION__));
	    *ret_err_msg = NULL;
	}
	else {
	    /* return pointer to server message */
	    syslog(LOG_ERR, "%s: accounting failed, server reply was %d "
		   "(%s)", __FUNCTION__, r, server->server_msg);
	    if (*ret_err_msg == NULL) {
		*ret_err_msg = "Accounting failed";
	    }
	    err = -1;
	    goto bail;
	}

 bail:
	if (tb) {
	    free(tb);
	}
	return(err);
}
예제 #5
0
void sighandler(int sig __Unused) {
    TACDEBUG(LOG_DEBUG, "caught signal %d", sig);
}