From 1119da92c3c47a2cb2a48d494f98ff10a6c32619 Mon Sep 17 00:00:00 2001 From: Walter de Jong Date: Thu, 28 Mar 2013 23:10:43 +0100 Subject: server is a struct { address, key } --- libtac/include/libtac.h | 4 ++-- libtac/lib/header.c | 2 +- pam_tacplus.c | 57 ++++++++++++++++++++++++++++++++----------------- support.c | 46 +++++++++++++++++++++------------------ support.h | 9 ++++++-- 5 files changed, 72 insertions(+), 46 deletions(-) diff --git a/libtac/include/libtac.h b/libtac/include/libtac.h index 36dc9b0..bcc5880 100644 --- a/libtac/include/libtac.h +++ b/libtac/include/libtac.h @@ -113,7 +113,7 @@ extern int tac_ver_patch; /* header.c */ extern int session_id; extern int tac_encryption; -extern char *tac_secret; +extern const char *tac_secret; extern char *tac_login; extern int tac_priv_lvl; extern int tac_authen_method; @@ -126,7 +126,7 @@ extern int tac_readtimeout_enable; extern int tac_timeout; int tac_connect(struct addrinfo **, char **, int); -int tac_connect_single(struct addrinfo *, char *); +int tac_connect_single(struct addrinfo *, const char *); char *tac_ntop(const struct sockaddr *, size_t); int tac_authen_send(int, const char *, char *, char *, diff --git a/libtac/lib/header.c b/libtac/lib/header.c index f361225..dd04c92 100644 --- a/libtac/lib/header.c +++ b/libtac/lib/header.c @@ -33,7 +33,7 @@ int session_id; int tac_encryption = 0; /* Pointer to TACACS+ shared secret string. */ -char *tac_secret = NULL; +const char *tac_secret = NULL; /* Pointer to TACACS+ shared login string. */ char *tac_login = NULL; /* default is PAP */ diff --git a/pam_tacplus.c b/pam_tacplus.c index 42d5f54..ea2478c 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c @@ -42,8 +42,8 @@ #endif /* address of server discovered by pam_sm_authenticate */ -static struct addrinfo *active_server = NULL; -static char *active_key = NULL; +static tacplus_server_t *active_server = NULL; + /* accounting task identifier */ static short int task_id = 0; @@ -169,7 +169,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, while ((status == PAM_SESSION_ERR) && (srv_i < tac_srv_no)) { int tac_fd; - tac_fd = tac_connect_single(tac_srv[srv_i], tac_srv_key[srv_i]); + tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key); if(tac_fd < 0) { _pam_log(LOG_WARNING, "%s: error sending %s (fd)", __FUNCTION__, typemsg); @@ -204,7 +204,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, for(srv_i = 0; srv_i < tac_srv_no; srv_i++) { int tac_fd; - tac_fd = tac_connect_single(tac_srv[srv_i], tac_srv_key[srv_i]); + tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key); if(tac_fd < 0) { _pam_log(LOG_WARNING, "%s: error sending %s (fd)", __FUNCTION__, typemsg); @@ -260,6 +260,7 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, int status = PAM_AUTH_ERR; user = pass = tty = r_addr = NULL; + active_server = NULL; ctrl = _pam_parse (argc, argv); @@ -305,7 +306,7 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, if (ctrl & PAM_TAC_DEBUG) syslog (LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i ); - tac_fd = tac_connect_single(tac_srv[srv_i], tac_srv_key[srv_i]); + tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key); if (tac_fd < 0) { _pam_log (LOG_ERR, "connection failed srv %d: %m", srv_i); if (srv_i == tac_srv_no-1) { @@ -335,9 +336,12 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, /* 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]; + active_server = &tac_srv[srv_i]; close(tac_fd); + + if (ctrl & PAM_TAC_DEBUG) + syslog (LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i ); + break; } } @@ -348,9 +352,12 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, /* 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]; + active_server = &tac_srv[srv_i]; close(tac_fd); + + if (ctrl & PAM_TAC_DEBUG) + syslog (LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i ); + break; } } @@ -417,7 +424,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: username obtained [%s]", __FUNCTION__, user); - + tty = _pam_get_terminal(pamh); if(!strncmp(tty, "/dev/", 5)) tty += 5; @@ -432,21 +439,21 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, 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) { + if(active_server == 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->ai_addr, active_server->ai_addrlen)); + tac_ntop(active_server->addr->ai_addr, active_server->addr->ai_addrlen)); /* checks for specific data required by TACACS+, which should be supplied in command line */ - if(tac_service == NULL || *tac_service == '\0') { + if(tac_service == NULL || !*tac_service) { _pam_log (LOG_ERR, "TACACS+ service type not configured"); return PAM_AUTH_ERR; } - if(tac_protocol == NULL || *tac_protocol == '\0') { + if(tac_protocol == NULL || !*tac_protocol) { _pam_log (LOG_ERR, "TACACS+ protocol type not configured"); return PAM_AUTH_ERR; } @@ -454,10 +461,12 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, tac_add_attrib(&attr, "service", tac_service); tac_add_attrib(&attr, "protocol", tac_protocol); - tac_fd = tac_connect_single(active_server, active_key); + tac_fd = tac_connect_single(active_server->addr, active_server->key); if(tac_fd < 0) { _pam_log (LOG_ERR, "TACACS+ server unavailable"); - if(arep.msg != NULL) free (arep.msg); + if(arep.msg != NULL) + free (arep.msg); + close(tac_fd); return PAM_AUTH_ERR; } @@ -468,7 +477,9 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, if(retval < 0) { _pam_log (LOG_ERR, "error getting authorization"); - if(arep.msg != NULL) free (arep.msg); + if(arep.msg != NULL) + free (arep.msg); + close(tac_fd); return PAM_AUTH_ERR; } @@ -482,7 +493,9 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, arep.status != AUTHOR_STATUS_PASS_REPL) { _pam_log (LOG_ERR, "TACACS+ authorisation failed for [%s]", user); - if(arep.msg != NULL) free (arep.msg); + if(arep.msg != NULL) + free (arep.msg); + close(tac_fd); return PAM_PERM_DENIED; } @@ -528,8 +541,12 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, } /* free returned attributes */ - if(arep.attr != NULL) tac_free_attrib(&arep.attr); - if(arep.msg != NULL) free (arep.msg); + if(arep.attr != NULL) + tac_free_attrib(&arep.attr); + + if(arep.msg != NULL) + free (arep.msg); + close(tac_fd); return status; diff --git a/support.c b/support.c index df09aba..101a8e0 100644 --- a/support.c +++ b/support.c @@ -27,10 +27,9 @@ #include "support.h" #include "pam_tacplus.h" -struct addrinfo *tac_srv[TAC_PLUS_MAXSERVERS]; +tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; int tac_srv_no = 0; -char *tac_srv_key[TAC_PLUS_MAXSERVERS]; -int tac_srv_key_no = 0; + char *tac_service = NULL; char *tac_protocol = NULL; char *tac_prompt = NULL; @@ -186,9 +185,11 @@ int tacacs_get_password (pam_handle_t * pamh, int flags int _pam_parse (int argc, const char **argv) { int ctrl = 0; + const char *current_secret = NULL; /* otherwise the list will grow with each call */ - tac_srv_no = tac_srv_key_no = 0; + memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); + tac_srv_no = 0; for (ctrl = 0; argc-- > 0; ++argv) { if (!strcmp (*argv, "debug")) { /* all */ @@ -238,7 +239,8 @@ int _pam_parse (int argc, const char **argv) { } if ((rv = getaddrinfo(server_buf, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { - tac_srv[tac_srv_no] = server; + tac_srv[tac_srv_no].addr = server; + tac_srv[tac_srv_no].key = current_secret; tac_srv_no++; } } else { @@ -251,13 +253,16 @@ int _pam_parse (int argc, const char **argv) { TAC_PLUS_MAXSERVERS); } } else if (!strncmp (*argv, "secret=", 7)) { - if(tac_srv_key_no < TAC_PLUS_MAXSERVERS) { - tac_srv_key[tac_srv_key_no] = (char *) _xcalloc (strlen (*argv + 7) + 1); - strcpy (tac_srv_key[tac_srv_key_no], *argv + 7); - tac_srv_key_no++; - } else { - _pam_log(LOG_ERR, "maximum number of secrets (%d) exceeded, skipping", - TAC_PLUS_MAXSERVERS); + int i; + + current_secret = *argv + 7; /* points right into argv (which is const) */ + + /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ + for(i = tac_srv_no-1; i >= 0; i--) { + if (tac_srv[i].key != NULL) + break; + + tac_srv[i].key = current_secret; } } else if (!strncmp (*argv, "timeout=", 8)) { tac_timeout = atoi(*argv + 8); @@ -269,15 +274,14 @@ int _pam_parse (int argc, const char **argv) { } } - if (tac_srv_key_no == 0) { - /* FIXME this should really be NULL - but watch out with breaking other code - */ - tac_srv_key[0] = ""; - tac_srv_key_no++; - } - for (;tac_srv_key_no < tac_srv_no;tac_srv_key_no++) { - tac_srv_key[tac_srv_key_no] = tac_srv_key[0]; + if (ctrl & PAM_TAC_DEBUG) { + int n; + + _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); + + for(n = 0; n < tac_srv_no; n++) { + _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%s' }", n, tac_ntop(tac_srv[n].addr->ai_addr, 0), tac_srv[n].key); + } } return ctrl; diff --git a/support.h b/support.h index 9662961..260dea6 100644 --- a/support.h +++ b/support.h @@ -26,9 +26,14 @@ #include -extern struct addrinfo *tac_srv[TAC_PLUS_MAXSERVERS]; -extern char *tac_srv_key[TAC_PLUS_MAXSERVERS]; +typedef struct { + struct addrinfo *addr; + const char *key; +} tacplus_server_t; + +extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; extern int tac_srv_no; + extern char *tac_service; extern char *tac_protocol; -- cgit v1.2.3