static void account(u_char *pak) { struct acct *acct_pak; u_char *p, *argsizep; struct acct_rec rec; struct identity identity; char **cmd_argp; int i, errors = 0, status; acct_pak = (struct acct *) (pak + TAC_PLUS_HDR_SIZE); /* Fill out accounting record structure */ memset(&rec, 0, sizeof(struct acct_rec)); if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_WATCHDOG) rec.acct_type = ACCT_TYPE_UPDATE; if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_START) rec.acct_type = ACCT_TYPE_START; if (acct_pak->flags & TAC_PLUS_ACCT_FLAG_STOP) rec.acct_type = ACCT_TYPE_STOP; rec.authen_method = acct_pak->authen_method; rec.authen_type = acct_pak->authen_type; rec.authen_service = acct_pak->authen_service; /* start of variable length data is here */ p = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE; /* skip arg cnts */ p += acct_pak->arg_cnt; /* zero out identity struct */ memset(&identity, 0, sizeof(struct identity)); identity.username = tac_make_string(p, (int)acct_pak->user_len); p += acct_pak->user_len; identity.NAS_name = tac_strdup(session.peer); identity.NAS_port = tac_make_string(p, (int)acct_pak->port_len); p += acct_pak->port_len; if (acct_pak->port_len <= 0) { strcpy(session.port, "unknown-port"); } else { strcpy(session.port, identity.NAS_port); } identity.NAC_address = tac_make_string(p, (int)acct_pak->rem_addr_len); p += acct_pak->rem_addr_len; identity.priv_lvl = acct_pak->priv_lvl; rec.identity = &identity; /* Now process cmd args */ argsizep = pak + TAC_PLUS_HDR_SIZE + TAC_ACCT_REQ_FIXED_FIELDS_SIZE; cmd_argp = (char **)tac_malloc(acct_pak->arg_cnt * sizeof(char *)); for (i = 0; i < (int)acct_pak->arg_cnt; i++) { cmd_argp[i] = tac_make_string(p, *argsizep); p += *argsizep++; } rec.args = cmd_argp; rec.num_args = acct_pak->arg_cnt; #ifdef MAXSESS /* Tally for MAXSESS counting */ loguser(&rec); #endif /* Do accounting */ if (wtmpfile) errors = do_wtmp(&rec); if (session.acctfile != NULL) errors += do_acct_file(&rec); if (session.flags & SESS_FLAG_ACCTSYSL) errors += do_acct_syslog(&rec); if (errors) { status = TAC_PLUS_ACCT_STATUS_ERROR; } else { status = TAC_PLUS_ACCT_STATUS_SUCCESS; } send_acct_reply(status, rec.msg, rec.admin_msg); free(identity.username); free(identity.NAS_name); free(identity.NAS_port); free(identity.NAC_address); for (i = 0; i < (int)acct_pak->arg_cnt; i++) { free(cmd_argp[i]); } free(cmd_argp); if (rec.msg) free(rec.msg); if (rec.admin_msg) free(rec.admin_msg); }
/* * 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); }