Ejemplo n.º 1
0
/* Checks given reply header for possible inconsistencies:
 *  1. reply type other than expected
 *  2. sequence number other than 2 or 4
 *  3. session_id different from one sent in request
 * Returns pointer to error message
 * or NULL when the header seems to be correct
 */
char *_tac_check_header(HDR *th, int type) {
    if(th->type != type) {
        TACSYSLOG(LOG_ERR,\
            "%s: unrelated reply, type %d, expected %d",\
            __FUNCTION__, th->type, type);
        return protocol_err_msg;
    } else if (1 == (th->seq_no % 2)) {
        TACSYSLOG(LOG_ERR, "%s: not a reply - seq_no %d not even",\
            __FUNCTION__, th->seq_no);
        return protocol_err_msg;
    } /* else if(ntohl(th->session_id) != session_id) {
        TACSYSLOG(LOG_ERR,\
            "%s: unrelated reply, received session_id %d != sent %d",\
            __FUNCTION__, ntohl(th->session_id), session_id);
        return protocol_err_msg;
    } */
    
    return NULL; /* header is ok */    
} /* check header */
Ejemplo n.º 2
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 */
Ejemplo n.º 3
0
/* this function sends a continue packet do TACACS+ server, asking
 * for validation of given password
 *
 * 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
 */
int tac_cont_send(int fd, char *pass) {
    HDR *th;        /* TACACS+ packet header */
    struct authen_cont tb;  /* continue body */
    int pass_len, bodylength, w;
    int pkt_len = 0;
    int ret = 0;
    u_char *pkt = NULL;

    th = _tac_req_header(TAC_PLUS_AUTHEN, 1);

    /* set some header options */
    th->version = TAC_PLUS_VER_0;
    th->seq_no = 3;       /* 1 = request, 2 = reply, 3 = continue, 4 = reply */
    th->encryption = tac_encryption ? TAC_PLUS_ENCRYPTED_FLAG : TAC_PLUS_UNENCRYPTED_FLAG;

    /* get size of submitted data */
    pass_len = strlen(pass);

    /* fill the body of message */
    tb.user_msg_len = htons(pass_len);
    tb.user_data_len = tb.flags = 0;

    /* fill body length in header */
    bodylength = TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE+0+pass_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(pkt);
        free(th);
        return LIBTAC_STATUS_WRITE_ERR;
    }

    /* build the packet */
    pkt = (u_char *) tac_xcalloc(1, bodylength);

    bcopy(&tb, pkt+pkt_len, TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE); /* packet body beginning */
    pkt_len += TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE;
    bcopy(pass, pkt+pkt_len, pass_len);  /* password */
    pkt_len += pass_len;

    /* pkt_len == bodylength ? */
    if (pkt_len != bodylength) {
        TACSYSLOG((LOG_ERR,\
            "%s: bodylength %d != pkt_len %d",\
            __FUNCTION__, bodylength, pkt_len))
        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;
    }

    free(pkt);
    free(th);
    TACDEBUG((LOG_DEBUG, "%s: exit status=%d", __FUNCTION__, ret))
    return ret;
} /* tac_cont_send */
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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, 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 */