void send_error_reply(int type, char *msg) { switch (type) { case TAC_PLUS_AUTHEN: send_authen_error(msg); return; case TAC_PLUS_AUTHOR: send_author_reply(AUTHOR_STATUS_ERROR, msg, NULL, 0, NULL); return; case TAC_PLUS_ACCT: send_acct_reply(TAC_PLUS_ACCT_STATUS_ERROR, msg, NULL); return; default: report(LOG_ERR, "Illegal type %d for send_error_reply", type); return; } /*NOTREACHED*/ return; }
/* * Come here when we receive an authorization START packet */ void author(u_char *pak) { HDR *hdr; struct author *apak; struct identity identity; #ifdef ACLS struct authen_data authen_data; #endif struct author_data author_data; u_char *p; u_char *argsizep; char **cmd_argp; int i, len; if (debug & DEBUG_AUTHOR_FLAG) report(LOG_DEBUG, "Start authorization request"); hdr = (HDR *)pak; apak = (struct author *)(pak + TAC_PLUS_HDR_SIZE); /* Do some sanity checks */ if (hdr->seq_no != 1) { send_error_reply(TAC_PLUS_AUTHOR, NULL); return; } /* Check if there's at least sizeof(struct author) of useful data */ if (ntohl(hdr->datalength) < TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE) { report(LOG_ERR, "%s: author minimum payload length: %zu, got: %u", session.peer, TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE, ntohl(hdr->datalength)); send_error_reply(TAC_PLUS_AUTHOR, NULL); return; } /* arg counts start here */ p = pak + TAC_PLUS_HDR_SIZE + TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE; /* Length checks */ len = TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE; len += apak->user_len + apak->port_len + apak->rem_addr_len + apak->arg_cnt; /* Is there enough space for apak->arg_cnt arguments? */ if (ntohl(hdr->datalength) < (TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE + apak->arg_cnt)) { report(LOG_ERR, "%s: author minimum payload length: %zu, got: %u", session.peer, TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE + apak->arg_cnt, ntohl(hdr->datalength)); send_error_reply(TAC_PLUS_AUTHOR, NULL); return; } for (i = 0; i < (int)apak->arg_cnt; i++) { len += p[i]; } if (len != ntohl(hdr->datalength)) { send_error_reply(TAC_PLUS_AUTHOR, NULL); return; } /* start of variable length data is here */ p = pak + TAC_PLUS_HDR_SIZE + TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE; /* arg length data starts here */ argsizep = p; p += apak->arg_cnt; memset(&author_data, 0, sizeof(struct author_data)); /* The identity structure */ /* zero out identity struct */ memset(&identity, 0, sizeof(struct identity)); identity.username = tac_make_string(p, (int)apak->user_len); p += apak->user_len; identity.NAS_name = tac_strdup(session.peer); #ifdef ACLS identity.NAS_ip = tac_strdup(session.peerip); #endif identity.NAS_port = tac_make_string(p, (int)apak->port_len); p += apak->port_len; if (apak->port_len <= 0) { strcpy(session.port, "unknown-port"); } else { strcpy(session.port, identity.NAS_port); } identity.NAC_address = tac_make_string(p, (int)apak->rem_addr_len); p += apak->rem_addr_len; identity.priv_lvl = apak->priv_lvl; /* The author_data structure */ author_data.id = &identity; /* user id */ /* FIXME: validate these fields */ author_data.authen_method = apak->authen_method; author_data.authen_type = apak->authen_type; author_data.service = apak->service; author_data.num_in_args = apak->arg_cnt; /* Space for args + NULL */ cmd_argp = (char **)tac_malloc(apak->arg_cnt * sizeof(char *)); /* p points to the start of args. Step thru them making strings */ for (i = 0; i < (int)apak->arg_cnt; i++) { cmd_argp[i] = tac_make_string(p, *argsizep); p += *argsizep++; } author_data.input_args = cmd_argp; /* input command arguments */ #ifdef ACLS authen_data.NAS_id = &identity; if (verify_host(author_data.id->username, &authen_data, S_acl, TAC_PLUS_RECURSE) != S_permit) { author_data.status = AUTHOR_STATUS_FAIL; } else #endif if (do_author(&author_data)) { report(LOG_ERR, "%s: do_author returned an error", session.peer); send_author_reply(AUTHOR_STATUS_ERROR, author_data.msg, author_data.admin_msg, author_data.num_out_args, author_data.output_args); return; } /* Send a reply packet */ send_author_reply(author_data.status, author_data.msg, author_data.admin_msg, author_data.num_out_args, author_data.output_args); if (debug) report(LOG_INFO, "authorization query for '%s' %s from %s %s", author_data.id->username && author_data.id->username[0] ? author_data.id->username : "******", author_data.id->NAS_port && author_data.id->NAS_port[0] ? author_data.id->NAS_port : "unknown", session.peer, (author_data.status == AUTHOR_STATUS_PASS_ADD || author_data.status == AUTHOR_STATUS_PASS_REPL) ? "accepted" : "rejected"); /* free the input args */ if (author_data.input_args) { for (i = 0; i < author_data.num_in_args; i++) free(author_data.input_args[i]); free(author_data.input_args); author_data.input_args = NULL; } /* free the output args */ if (author_data.output_args) { for (i = 0; i < author_data.num_out_args; i++) free(author_data.output_args[i]); free(author_data.output_args); author_data.output_args = NULL; } if (author_data.msg) free(author_data.msg); if (author_data.admin_msg) free(author_data.admin_msg); free(identity.username); free(identity.NAS_name); #ifdef ACLS free(identity.NAS_ip); #endif free(identity.NAS_port); free(identity.NAC_address); }