|
version 1.1.1.2, 2013/07/22 08:44:29
|
version 1.1.1.4, 2021/03/17 00:39:23
|
|
Line 18
|
Line 18
|
| #include "util.h" |
#include "util.h" |
| |
|
| #ifdef USE_PAM |
#ifdef USE_PAM |
| #include <security/pam_appl.h> | #include <security/pam_appl.h> |
| #endif |
#endif |
| #ifdef USE_SYSTEM |
#ifdef USE_SYSTEM |
| #if __FreeBSD_version >= 900007 |
#if __FreeBSD_version >= 900007 |
|
Line 32
|
Line 32
|
| /* |
/* |
| * DEFINITIONS |
* DEFINITIONS |
| */ |
*/ |
| | |
| #ifdef USE_OPIE |
#ifdef USE_OPIE |
| #define OPIE_ALG_MD5 5 | #define OPIE_ALG_MD5 5 |
| #endif |
#endif |
| | |
| /* |
/* |
| * INTERNAL FUNCTIONS |
* INTERNAL FUNCTIONS |
| */ |
*/ |
| |
|
| static void AuthTimeout(void *arg); | static void AuthTimeout(void *arg); |
| static int AuthGetExternalPassword(char * extcmd, char *authname, | static int |
| char *password, size_t passlen); | AuthGetExternalPassword(const char *extcmd, char *authname, |
| static void AuthAsync(void *arg); | char *password, size_t passlen); |
| static void AuthAsyncFinish(void *arg, int was_canceled); | static void AuthAsync(void *arg); |
| static int AuthPreChecks(AuthData auth); | static void AuthAsyncFinish(void *arg, int was_canceled); |
| static void AuthAccount(void *arg); | static int AuthPreChecks(AuthData auth); |
| static void AuthAccountFinish(void *arg, int was_canceled); | static void AuthAccount(void *arg); |
| static void AuthInternal(AuthData auth); | static void AuthAccountFinish(void *arg, int was_canceled); |
| static int AuthExternal(AuthData auth); | static void AuthInternal(AuthData auth); |
| static int AuthExternalAcct(AuthData auth); | static int AuthExternal(AuthData auth); |
| | static int AuthExternalAcct(AuthData auth); |
| | |
| #ifdef USE_SYSTEM |
#ifdef USE_SYSTEM |
| static void AuthSystem(AuthData auth); | static void AuthSystem(AuthData auth); |
| static int AuthSystemAcct(AuthData auth); | static int AuthSystemAcct(AuthData auth); |
| | |
| #endif |
#endif |
| #ifdef USE_PAM |
#ifdef USE_PAM |
| static void AuthPAM(AuthData auth); | static void AuthPAM(AuthData auth); |
| static int AuthPAMAcct(AuthData auth); | static int AuthPAMAcct(AuthData auth); |
| static int pam_conv(int n, const struct pam_message **msg, | static int |
| struct pam_response **resp, void *data); | pam_conv(int n, const struct pam_message **msg, |
| | struct pam_response **resp, void *data); |
| | |
| #endif |
#endif |
| #ifdef USE_OPIE |
#ifdef USE_OPIE |
| static void AuthOpie(AuthData auth); | static void AuthOpie(AuthData auth); |
| | |
| #endif |
#endif |
| static const char *AuthCode(int proto, u_char code, char *buf, size_t len); | static const char *AuthCode(int proto, u_char code, char *buf, size_t len); |
| static int AuthSetCommand(Context ctx, int ac, char *av[], void *arg); | static int AuthSetCommand(Context ctx, int ac, const char *const av[], const void *arg); |
| |
|
| /* Set menu options */ | /* Set menu options */ |
| enum { | enum { |
| SET_ACCEPT, | SET_ACCEPT, |
| SET_DENY, | SET_DENY, |
| SET_ENABLE, | SET_ENABLE, |
| SET_DISABLE, | SET_DISABLE, |
| SET_YES, | SET_YES, |
| SET_NO, | SET_NO, |
| SET_AUTHNAME, | SET_AUTHNAME, |
| SET_PASSWORD, | SET_PASSWORD, |
| SET_EXTAUTH_SCRIPT, | SET_EXTAUTH_SCRIPT, |
| SET_EXTACCT_SCRIPT, | SET_EXTACCT_SCRIPT, |
| SET_MAX_LOGINS, | SET_MAX_LOGINS, |
| SET_ACCT_UPDATE, | SET_ACCT_UPDATE, |
| SET_ACCT_UPDATE_LIMIT_IN, | SET_ACCT_UPDATE_LIMIT_IN, |
| SET_ACCT_UPDATE_LIMIT_OUT, | SET_ACCT_UPDATE_LIMIT_OUT, |
| SET_TIMEOUT | SET_TIMEOUT |
| }; | }; |
| |
|
| /* |
/* |
| * GLOBAL VARIABLES |
* GLOBAL VARIABLES |
| */ |
*/ |
| |
|
| const struct cmdtab AuthSetCmds[] = { | const struct cmdtab AuthSetCmds[] = { |
| { "max-logins {num}", "Max concurrent logins", | {"max-logins {num} [CI]", "Max concurrent logins", |
| AuthSetCommand, NULL, 2, (void *) SET_MAX_LOGINS }, | AuthSetCommand, NULL, 2, (void *)SET_MAX_LOGINS}, |
| { "authname {name}", "Authentication name", | {"authname {name}", "Authentication name", |
| AuthSetCommand, NULL, 2, (void *) SET_AUTHNAME }, | AuthSetCommand, NULL, 2, (void *)SET_AUTHNAME}, |
| { "password {pass}", "Authentication password", | {"password {pass}", "Authentication password", |
| AuthSetCommand, NULL, 2, (void *) SET_PASSWORD }, | AuthSetCommand, NULL, 2, (void *)SET_PASSWORD}, |
| { "extauth-script {script}", "Authentication script", | {"extauth-script {script}", "Authentication script", |
| AuthSetCommand, NULL, 2, (void *) SET_EXTAUTH_SCRIPT }, | AuthSetCommand, NULL, 2, (void *)SET_EXTAUTH_SCRIPT}, |
| { "extacct-script {script}", "Accounting script", | {"extacct-script {script}", "Accounting script", |
| AuthSetCommand, NULL, 2, (void *) SET_EXTACCT_SCRIPT }, | AuthSetCommand, NULL, 2, (void *)SET_EXTACCT_SCRIPT}, |
| { "acct-update {seconds}", "set update interval", | {"acct-update {seconds}", "set update interval", |
| AuthSetCommand, NULL, 2, (void *) SET_ACCT_UPDATE }, | AuthSetCommand, NULL, 2, (void *)SET_ACCT_UPDATE}, |
| { "update-limit-in {bytes}", "set update suppresion limit", | {"update-limit-in {bytes}", "set update suppresion limit", |
| AuthSetCommand, NULL, 2, (void *) SET_ACCT_UPDATE_LIMIT_IN }, | AuthSetCommand, NULL, 2, (void *)SET_ACCT_UPDATE_LIMIT_IN}, |
| { "update-limit-out {bytes}", "set update suppresion limit", | {"update-limit-out {bytes}", "set update suppresion limit", |
| AuthSetCommand, NULL, 2, (void *) SET_ACCT_UPDATE_LIMIT_OUT }, | AuthSetCommand, NULL, 2, (void *)SET_ACCT_UPDATE_LIMIT_OUT}, |
| { "timeout {seconds}", "set auth timeout", | {"timeout {seconds}", "set auth timeout", |
| AuthSetCommand, NULL, 2, (void *) SET_TIMEOUT }, | AuthSetCommand, NULL, 2, (void *)SET_TIMEOUT}, |
| { "accept [opt ...]", "Accept option", | {"accept [opt ...]", "Accept option", |
| AuthSetCommand, NULL, 2, (void *) SET_ACCEPT }, | AuthSetCommand, NULL, 2, (void *)SET_ACCEPT}, |
| { "deny [opt ...]", "Deny option", | {"deny [opt ...]", "Deny option", |
| AuthSetCommand, NULL, 2, (void *) SET_DENY }, | AuthSetCommand, NULL, 2, (void *)SET_DENY}, |
| { "enable [opt ...]", "Enable option", | {"enable [opt ...]", "Enable option", |
| AuthSetCommand, NULL, 2, (void *) SET_ENABLE }, | AuthSetCommand, NULL, 2, (void *)SET_ENABLE}, |
| { "disable [opt ...]", "Disable option", | {"disable [opt ...]", "Disable option", |
| AuthSetCommand, NULL, 2, (void *) SET_DISABLE }, | AuthSetCommand, NULL, 2, (void *)SET_DISABLE}, |
| { "yes [opt ...]", "Enable and accept option", | {"yes [opt ...]", "Enable and accept option", |
| AuthSetCommand, NULL, 2, (void *) SET_YES }, | AuthSetCommand, NULL, 2, (void *)SET_YES}, |
| { "no [opt ...]", "Disable and deny option", | {"no [opt ...]", "Disable and deny option", |
| AuthSetCommand, NULL, 2, (void *) SET_NO }, | AuthSetCommand, NULL, 2, (void *)SET_NO}, |
| { NULL }, | {NULL, NULL, NULL, NULL, 0, NULL}, |
| }; | }; |
| |
|
| const u_char gMsoftZeros[32]; | const u_char gMsoftZeros[32]; |
| int gMaxLogins = 0; /* max number of concurrent logins per user */ | static unsigned gMaxLogins = 0; /* max number of concurrent logins per |
| int gMaxLoginsCI = 0; | * user */ |
| | static unsigned gMaxLoginsCI = 0; |
| |
|
| /* |
/* |
| * INTERNAL VARIABLES |
* INTERNAL VARIABLES |
| */ |
*/ |
| |
|
| static struct confinfo gConfList[] = { | static const struct confinfo gConfList[] = { |
| { 0, AUTH_CONF_RADIUS_AUTH, "radius-auth" }, | {0, AUTH_CONF_RADIUS_AUTH, "radius-auth"}, |
| { 0, AUTH_CONF_RADIUS_ACCT, "radius-acct" }, | {0, AUTH_CONF_RADIUS_ACCT, "radius-acct"}, |
| { 0, AUTH_CONF_INTERNAL, "internal" }, | {0, AUTH_CONF_INTERNAL, "internal"}, |
| { 0, AUTH_CONF_EXT_AUTH, "ext-auth" }, | {0, AUTH_CONF_EXT_AUTH, "ext-auth"}, |
| { 0, AUTH_CONF_EXT_ACCT, "ext-acct" }, | {0, AUTH_CONF_EXT_ACCT, "ext-acct"}, |
| #ifdef USE_SYSTEM |
#ifdef USE_SYSTEM |
| { 0, AUTH_CONF_SYSTEM_AUTH, "system-auth" }, | {0, AUTH_CONF_SYSTEM_AUTH, "system-auth"}, |
| { 0, AUTH_CONF_SYSTEM_ACCT, "system-acct" }, | {0, AUTH_CONF_SYSTEM_ACCT, "system-acct"}, |
| #endif |
#endif |
| #ifdef USE_PAM |
#ifdef USE_PAM |
| { 0, AUTH_CONF_PAM_AUTH, "pam-auth" }, | {0, AUTH_CONF_PAM_AUTH, "pam-auth"}, |
| { 0, AUTH_CONF_PAM_ACCT, "pam-acct" }, | {0, AUTH_CONF_PAM_ACCT, "pam-acct"}, |
| #endif |
#endif |
| #ifdef USE_OPIE |
#ifdef USE_OPIE |
| { 0, AUTH_CONF_OPIE, "opie" }, | {0, AUTH_CONF_OPIE, "opie"}, |
| #endif |
#endif |
| { 0, AUTH_CONF_ACCT_MANDATORY, "acct-mandatory" }, | {0, AUTH_CONF_ACCT_MANDATORY, "acct-mandatory"}, |
| { 0, 0, NULL }, | {0, 0, NULL}, |
| }; | }; |
| |
|
| void |
void |
| ACLCopy(struct acl *src, struct acl **dst) |
ACLCopy(struct acl *src, struct acl **dst) |
| { |
{ |
| while (src != NULL) { | while (src != NULL) { |
| *dst = Mdup(MB_AUTH, src, sizeof(struct acl) + strlen(src->rule)); | *dst = Mdup(MB_AUTH, src, sizeof(struct acl) + strlen(src->rule)); |
| src = src->next; | src = src->next; |
| dst = &((*dst)->next); | dst = &((*dst)->next); |
| }; | }; |
| *dst = NULL; | *dst = NULL; |
| } |
} |
| |
|
| void |
void |
| ACLDestroy(struct acl *acl) |
ACLDestroy(struct acl *acl) |
| { |
{ |
| struct acl *acl1; | struct acl *acl1; |
| |
|
| while (acl != NULL) { | while (acl != NULL) { |
| acl1 = acl->next; | acl1 = acl->next; |
| Freee(acl); | Freee(acl); |
| acl = acl1; | acl = acl1; |
| }; | }; |
| } |
} |
| |
|
| void authparamsInit(struct authparams *ap) { | void |
| memset(ap,0,sizeof(struct authparams)); | authparamsInit(struct authparams *ap) |
| ap->eapmsg = NULL; | { |
| ap->state = NULL; | memset(ap, 0, sizeof(struct authparams)); |
| ap->class = NULL; | ap->eapmsg = NULL; |
| ap->msdomain = NULL; | ap->state = NULL; |
| | ap->class = NULL; |
| | ap->filter_id = NULL; |
| | ap->msdomain = NULL; |
| #ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
| ap->ifdescr = NULL; | ap->ifdescr = NULL; |
| #endif |
#endif |
| SLIST_INIT(&ap->routes); | SLIST_INIT(&ap->routes); |
| } |
} |
| |
|
| void authparamsDestroy(struct authparams *ap) { | void |
| IfaceRoute r; | authparamsDestroy(struct authparams *ap) |
| | { |
| | IfaceRoute r; |
| | |
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| int i; | int i; |
| #endif |
#endif |
| |
|
| Freee(ap->eapmsg); |
|
| Freee(ap->state); |
|
| Freee(ap->class); |
|
| |
|
| |
Freee(ap->eapmsg); |
| |
Freee(ap->state); |
| |
Freee(ap->class); |
| |
Freee(ap->filter_id); |
| |
|
| #ifdef USE_IPFW |
#ifdef USE_IPFW |
| ACLDestroy(ap->acl_rule); | ACLDestroy(ap->acl_rule); |
| ACLDestroy(ap->acl_pipe); | ACLDestroy(ap->acl_pipe); |
| ACLDestroy(ap->acl_queue); | ACLDestroy(ap->acl_queue); |
| ACLDestroy(ap->acl_table); | ACLDestroy(ap->acl_table); |
| #endif /* USE_IPFW */ | #endif /* USE_IPFW */ |
| |
|
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| for (i = 0; i < ACL_FILTERS; i++) | for (i = 0; i < ACL_FILTERS; i++) |
| ACLDestroy(ap->acl_filters[i]); | ACLDestroy(ap->acl_filters[i]); |
| for (i = 0; i < ACL_DIRS; i++) | for (i = 0; i < ACL_DIRS; i++) |
| ACLDestroy(ap->acl_limits[i]); | ACLDestroy(ap->acl_limits[i]); |
| #endif /* USE_NG_BPF */ | #endif /* USE_NG_BPF */ |
| |
|
| while ((r = SLIST_FIRST(&ap->routes)) != NULL) { | while ((r = SLIST_FIRST(&ap->routes)) != NULL) { |
| SLIST_REMOVE_HEAD(&ap->routes, next); | SLIST_REMOVE_HEAD(&ap->routes, next); |
| Freee(r); | Freee(r); |
| } | } |
| |
|
| Freee(ap->msdomain); | Freee(ap->msdomain); |
| #ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
| Freee(ap->ifdescr); | Freee(ap->ifdescr); |
| #endif |
#endif |
| | |
| memset(ap,0,sizeof(struct authparams)); | memset(ap, 0, sizeof(struct authparams)); |
| } |
} |
| |
|
| void authparamsCopy(struct authparams *src, struct authparams *dst) { | void |
| IfaceRoute r, r1; | authparamsCopy(struct authparams *src, struct authparams *dst) |
| | { |
| | IfaceRoute r, r1; |
| | |
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| int i; | int i; |
| | |
| #endif |
#endif |
| |
|
| memcpy(dst,src,sizeof(struct authparams)); | memcpy(dst, src, sizeof(struct authparams)); |
| | |
| if (src->eapmsg) | |
| dst->eapmsg = Mdup(MB_AUTH, src->eapmsg, src->eapmsg_len); | |
| if (src->state) | |
| dst->state = Mdup(MB_AUTH, src->state, src->state_len); | |
| if (src->class) | |
| dst->class = Mdup(MB_AUTH, src->class, src->class_len); | |
| |
|
| |
if (src->eapmsg) |
| |
dst->eapmsg = Mdup(MB_AUTH, src->eapmsg, src->eapmsg_len); |
| |
if (src->state) |
| |
dst->state = Mdup(MB_AUTH, src->state, src->state_len); |
| |
if (src->class) |
| |
dst->class = Mdup(MB_AUTH, src->class, src->class_len); |
| |
if (src->filter_id) |
| |
dst->filter_id = Mstrdup(MB_AUTH, src->filter_id); |
| |
|
| #ifdef USE_IPFW |
#ifdef USE_IPFW |
| ACLCopy(src->acl_rule, &dst->acl_rule); | ACLCopy(src->acl_rule, &dst->acl_rule); |
| ACLCopy(src->acl_pipe, &dst->acl_pipe); | ACLCopy(src->acl_pipe, &dst->acl_pipe); |
| ACLCopy(src->acl_queue, &dst->acl_queue); | ACLCopy(src->acl_queue, &dst->acl_queue); |
| ACLCopy(src->acl_table, &dst->acl_table); | ACLCopy(src->acl_table, &dst->acl_table); |
| #endif /* USE_IPFW */ | #endif /* USE_IPFW */ |
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| for (i = 0; i < ACL_FILTERS; i++) | for (i = 0; i < ACL_FILTERS; i++) |
| ACLCopy(src->acl_filters[i], &dst->acl_filters[i]); | ACLCopy(src->acl_filters[i], &dst->acl_filters[i]); |
| for (i = 0; i < ACL_DIRS; i++) | for (i = 0; i < ACL_DIRS; i++) |
| ACLCopy(src->acl_limits[i], &dst->acl_limits[i]); | ACLCopy(src->acl_limits[i], &dst->acl_limits[i]); |
| #endif |
#endif |
| |
|
| SLIST_INIT(&dst->routes); | SLIST_INIT(&dst->routes); |
| SLIST_FOREACH(r, &src->routes, next) { | SLIST_FOREACH(r, &src->routes, next) { |
| r1 = Mdup(MB_AUTH, r, sizeof(*r1)); | r1 = Mdup(MB_AUTH, r, sizeof(*r1)); |
| SLIST_INSERT_HEAD(&dst->routes, r1, next); | SLIST_INSERT_HEAD(&dst->routes, r1, next); |
| } | } |
| |
|
| if (src->msdomain) | if (src->msdomain) |
| dst->msdomain = Mstrdup(MB_AUTH, src->msdomain); | dst->msdomain = Mstrdup(MB_AUTH, src->msdomain); |
| #ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
| if (src->ifdescr) | if (src->ifdescr) |
| dst->ifdescr = Mstrdup(MB_AUTH, src->ifdescr); | dst->ifdescr = Mstrdup(MB_AUTH, src->ifdescr); |
| #endif |
#endif |
| } |
} |
| |
|
| void authparamsMove(struct authparams *src, struct authparams *dst) | void |
| | authparamsMove(struct authparams *src, struct authparams *dst) |
| { |
{ |
| memcpy(dst,src,sizeof(struct authparams)); | memcpy(dst, src, sizeof(struct authparams)); |
| memset(src,0,sizeof(struct authparams)); | memset(src, 0, sizeof(struct authparams)); |
| } |
} |
| |
|
| /* |
/* |
|
Line 281 void authparamsMove(struct authparams *src, struct aut
|
Line 302 void authparamsMove(struct authparams *src, struct aut
|
| void |
void |
| AuthInit(Link l) |
AuthInit(Link l) |
| { |
{ |
| AuthConf const ac = &l->lcp.auth.conf; | AuthConf const ac = &l->lcp.auth.conf; |
| | |
| ac->timeout = 40; | |
| Enable(&ac->options, AUTH_CONF_INTERNAL); | |
| Enable(&ac->options, AUTH_CONF_ACCT_MANDATORY); | |
| |
|
| EapInit(l); | ac->timeout = 40; |
| RadiusInit(l); | Enable(&ac->options, AUTH_CONF_INTERNAL); |
| | Enable(&ac->options, AUTH_CONF_ACCT_MANDATORY); |
| | |
| | EapInit(l); |
| | RadiusInit(l); |
| } |
} |
| |
|
| /* |
/* |
|
Line 300 AuthInit(Link l)
|
Line 321 AuthInit(Link l)
|
| void |
void |
| AuthInst(Auth auth, Auth autht) |
AuthInst(Auth auth, Auth autht) |
| { |
{ |
| memcpy(auth, autht, sizeof(*auth)); | memcpy(auth, autht, sizeof(*auth)); |
| if (auth->conf.extauth_script) | if (auth->conf.extauth_script) |
| autht->conf.extauth_script = Mstrdup(MB_AUTH, auth->conf.extauth_script); | autht->conf.extauth_script = Mstrdup(MB_AUTH, auth->conf.extauth_script); |
| if (auth->conf.extacct_script) | if (auth->conf.extacct_script) |
| autht->conf.extacct_script = Mstrdup(MB_AUTH, auth->conf.extacct_script); | autht->conf.extacct_script = Mstrdup(MB_AUTH, auth->conf.extacct_script); |
| } |
} |
| |
|
| /* |
/* |
|
Line 314 AuthInst(Auth auth, Auth autht)
|
Line 335 AuthInst(Auth auth, Auth autht)
|
| void |
void |
| AuthShutdown(Link l) |
AuthShutdown(Link l) |
| { |
{ |
| Auth a = &l->lcp.auth; | Auth a = &l->lcp.auth; |
| | |
| if (a->thread) | if (a->thread) |
| paction_cancel(&a->thread); | paction_cancel(&a->thread); |
| if (a->acct_thread) | if (a->acct_thread) |
| paction_cancel(&a->acct_thread); | paction_cancel(&a->acct_thread); |
| Freee(a->conf.extauth_script); | Freee(a->conf.extauth_script); |
| Freee(a->conf.extacct_script); | Freee(a->conf.extacct_script); |
| } |
} |
| |
|
| /* |
/* |
|
Line 333 AuthShutdown(Link l)
|
Line 354 AuthShutdown(Link l)
|
| void |
void |
| AuthStart(Link l) |
AuthStart(Link l) |
| { |
{ |
| Auth a = &l->lcp.auth; | Auth a = &l->lcp.auth; |
| |
|
| /* generate a uniq session id */ | /* generate a uniq session id */ |
| snprintf(l->session_id, AUTH_MAX_SESSIONID, "%d-%s", | snprintf(l->session_id, AUTH_MAX_SESSIONID, "%d-%s", |
| (int)(time(NULL) % 10000000), l->name); | (int)(time(NULL) % 10000000), l->name); |
| |
|
| authparamsInit(&a->params); | authparamsInit(&a->params); |
| | |
| /* What auth protocols were negotiated by LCP? */ | |
| a->self_to_peer = l->lcp.peer_auth; | |
| a->peer_to_self = l->lcp.want_auth; | |
| a->self_to_peer_alg = l->lcp.peer_alg; | |
| a->peer_to_self_alg = l->lcp.want_alg; | |
| |
|
| /* remember self's name */ | /* What auth protocols were negotiated by LCP? */ |
| PhysGetSelfName(l, a->params.selfname, sizeof(a->params.selfname)); | a->self_to_peer = l->lcp.peer_auth; |
| | a->peer_to_self = l->lcp.want_auth; |
| /* remember peer's name */ | a->self_to_peer_alg = l->lcp.peer_alg; |
| PhysGetPeerName(l, a->params.peername, sizeof(a->params.peername)); | a->peer_to_self_alg = l->lcp.want_alg; |
| | |
| /* remember self's IP address */ | |
| PhysGetSelfAddr(l, a->params.selfaddr, sizeof(a->params.selfaddr)); | |
| | |
| /* remember peer's IP address */ | |
| PhysGetPeerAddr(l, a->params.peeraddr, sizeof(a->params.peeraddr)); | |
| | |
| /* remember peer's TCP or UDP port */ | |
| PhysGetPeerPort(l, a->params.peerport, sizeof(a->params.peerport)); | |
| | |
| /* remember peer's MAC address */ | |
| PhysGetPeerMacAddr(l, a->params.peermacaddr, sizeof(a->params.peermacaddr)); | |
| | |
| /* remember peer's iface */ | |
| PhysGetPeerIface(l, a->params.peeriface, sizeof(a->params.peeriface)); | |
| | |
| /* remember calling number */ | |
| PhysGetCallingNum(l, a->params.callingnum, sizeof(a->params.callingnum)); | |
| | |
| /* remember called number */ | |
| PhysGetCalledNum(l, a->params.callednum, sizeof(a->params.callednum)); | |
| | |
| Log(LG_AUTH, ("[%s] %s: auth: peer wants %s, I want %s", | |
| Pref(&l->lcp.fsm), Fsm(&l->lcp.fsm), | |
| a->self_to_peer ? ProtoName(a->self_to_peer) : "nothing", | |
| a->peer_to_self ? ProtoName(a->peer_to_self) : "nothing")); | |
| |
|
| /* Is there anything to do? */ | /* remember self's name */ |
| if (!a->self_to_peer && !a->peer_to_self) { | PhysGetSelfName(l, a->params.selfname, sizeof(a->params.selfname)); |
| LcpAuthResult(l, TRUE); | |
| return; | |
| } | |
| |
|
| /* Start global auth timer */ | /* remember peer's name */ |
| TimerInit(&a->timer, "AuthTimer", | PhysGetPeerName(l, a->params.peername, sizeof(a->params.peername)); |
| l->lcp.auth.conf.timeout * SECONDS, AuthTimeout, l); | |
| TimerStart(&a->timer); | |
| |
|
| /* Start my auth to him */ | /* remember self's IP address */ |
| switch (a->self_to_peer) { | PhysGetSelfAddr(l, a->params.selfaddr, sizeof(a->params.selfaddr)); |
| case 0: | |
| break; | |
| case PROTO_PAP: | |
| PapStart(l, AUTH_SELF_TO_PEER); | |
| break; | |
| case PROTO_CHAP: | |
| ChapStart(l, AUTH_SELF_TO_PEER); | |
| break; | |
| case PROTO_EAP: | |
| EapStart(l, AUTH_SELF_TO_PEER); | |
| break; | |
| default: | |
| assert(0); | |
| } | |
| |
|
| /* Start his auth to me */ | /* remember peer's IP address */ |
| switch (a->peer_to_self) { | PhysGetPeerAddr(l, a->params.peeraddr, sizeof(a->params.peeraddr)); |
| case 0: | |
| break; | /* remember peer's TCP or UDP port */ |
| case PROTO_PAP: | PhysGetPeerPort(l, a->params.peerport, sizeof(a->params.peerport)); |
| PapStart(l, AUTH_PEER_TO_SELF); | |
| break; | /* remember peer's MAC address */ |
| case PROTO_CHAP: | PhysGetPeerMacAddr(l, a->params.peermacaddr, sizeof(a->params.peermacaddr)); |
| ChapStart(l, AUTH_PEER_TO_SELF); | |
| break; | /* remember peer's iface */ |
| case PROTO_EAP: | PhysGetPeerIface(l, a->params.peeriface, sizeof(a->params.peeriface)); |
| EapStart(l, AUTH_PEER_TO_SELF); | |
| break; | /* remember calling number */ |
| default: | PhysGetCallingNum(l, a->params.callingnum, sizeof(a->params.callingnum)); |
| assert(0); | |
| } | /* remember called number */ |
| | PhysGetCalledNum(l, a->params.callednum, sizeof(a->params.callednum)); |
| | |
| | Log(LG_AUTH, ("[%s] %s: auth: peer wants %s, I want %s", |
| | Pref(&l->lcp.fsm), Fsm(&l->lcp.fsm), |
| | a->self_to_peer ? ProtoName(a->self_to_peer) : "nothing", |
| | a->peer_to_self ? ProtoName(a->peer_to_self) : "nothing")); |
| | |
| | /* Is there anything to do? */ |
| | if (!a->self_to_peer && !a->peer_to_self) { |
| | LcpAuthResult(l, TRUE); |
| | return; |
| | } |
| | /* Start global auth timer */ |
| | TimerInit(&a->timer, "AuthTimer", |
| | l->lcp.auth.conf.timeout * SECONDS, AuthTimeout, l); |
| | TimerStart(&a->timer); |
| | |
| | /* Start my auth to him */ |
| | switch (a->self_to_peer) { |
| | case 0: |
| | break; |
| | case PROTO_PAP: |
| | PapStart(l, AUTH_SELF_TO_PEER); |
| | break; |
| | case PROTO_CHAP: |
| | ChapStart(l, AUTH_SELF_TO_PEER); |
| | break; |
| | case PROTO_EAP: |
| | EapStart(l, AUTH_SELF_TO_PEER); |
| | break; |
| | default: |
| | assert(0); |
| | } |
| | |
| | /* Start his auth to me */ |
| | switch (a->peer_to_self) { |
| | case 0: |
| | break; |
| | case PROTO_PAP: |
| | PapStart(l, AUTH_PEER_TO_SELF); |
| | break; |
| | case PROTO_CHAP: |
| | ChapStart(l, AUTH_PEER_TO_SELF); |
| | break; |
| | case PROTO_EAP: |
| | EapStart(l, AUTH_PEER_TO_SELF); |
| | break; |
| | default: |
| | assert(0); |
| | } |
| } |
} |
| |
|
| /* |
/* |
|
Line 434 AuthStart(Link l)
|
Line 454 AuthStart(Link l)
|
| void |
void |
| AuthInput(Link l, int proto, Mbuf bp) |
AuthInput(Link l, int proto, Mbuf bp) |
| { |
{ |
| AuthData auth; | AuthData auth; |
| int len; | struct fsmheader fsmh; |
| struct fsmheader fsmh; | u_char *pkt; |
| u_char *pkt; | char buf[16]; |
| char buf[16]; | u_short len; |
| | uint16_t fsmh_len; |
| |
|
| /* Sanity check */ | /* Sanity check */ |
| if (l->lcp.phase != PHASE_AUTHENTICATE && l->lcp.phase != PHASE_NETWORK) { | if (l->lcp.phase != PHASE_AUTHENTICATE && l->lcp.phase != PHASE_NETWORK) { |
| Log(LG_AUTH, ("[%s] AUTH: rec'd stray packet", l->name)); | Log(LG_ERR | LG_AUTH, ("[%s] AUTH: rec'd stray packet", l->name)); |
| mbfree(bp); | mbfree(bp); |
| return; | return; |
| } | } |
| | len = MBLEN(bp); |
| |
|
| len = MBLEN(bp); | /* Sanity check length */ |
| | if (len < sizeof(fsmh)) { |
| | Log(LG_ERR | LG_AUTH, ("[%s] AUTH: rec'd runt packet: %hu bytes", |
| | l->name, len)); |
| | mbfree(bp); |
| | return; |
| | } |
| |
|
| /* Sanity check length */ | bp = mbread(bp, &fsmh, sizeof(fsmh)); |
| if (len < sizeof(fsmh)) { | |
| Log(LG_AUTH, ("[%s] AUTH: rec'd runt packet: %d bytes", | |
| l->name, len)); | |
| mbfree(bp); | |
| return; | |
| } | |
| |
|
| auth = AuthDataNew(l); | fsmh_len = ntohs(fsmh.length); |
| auth->proto = proto; | if (len > fsmh_len) { |
| | /* Sanity check length */ |
| | if (fsmh_len < sizeof(fsmh)) { |
| | Log(LG_ERR | LG_AUTH, ("[%s] AUTH: bad length: says %hu, rec'd %hu", |
| | l->name, fsmh_len, len)); |
| | mbfree(bp); |
| | return; |
| | } |
| | len = fsmh_len; |
| | } |
| |
|
| bp = mbread(bp, &fsmh, sizeof(fsmh)); | len -= sizeof(fsmh); |
| if (len > ntohs(fsmh.length)) | pkt = MBDATA(bp); |
| len = ntohs(fsmh.length); | |
| len -= sizeof(fsmh); | |
| |
|
| pkt = MBDATA(bp); | if (proto == PROTO_EAP && bp) { |
| | Log(LG_AUTH, ("[%s] %s: rec'd %s #%d len: %hu, type: %s", l->name, |
| | ProtoName(proto), AuthCode(proto, fsmh.code, buf, sizeof(buf)), fsmh.id, |
| | fsmh_len, EapType(pkt[0]))); |
| | } else { |
| | Log(LG_AUTH, ("[%s] %s: rec'd %s #%d len: %hu", l->name, |
| | ProtoName(proto), AuthCode(proto, fsmh.code, buf, sizeof(buf)), fsmh.id, |
| | fsmh_len)); |
| | } |
| |
|
| if (proto == PROTO_EAP && bp) { | auth = AuthDataNew(l); |
| Log(LG_AUTH, ("[%s] %s: rec'd %s #%d len: %d, type: %s", l->name, | auth->proto = proto; |
| ProtoName(proto), AuthCode(proto, fsmh.code, buf, sizeof(buf)), fsmh.id, | auth->id = fsmh.id; |
| ntohs(fsmh.length), EapType(pkt[0]))); | auth->code = fsmh.code; |
| } else { | /* Status defaults to undefined */ |
| Log(LG_AUTH, ("[%s] %s: rec'd %s #%d len: %d", l->name, | auth->status = AUTH_STATUS_UNDEF; |
| ProtoName(proto), AuthCode(proto, fsmh.code, buf, sizeof(buf)), fsmh.id, | |
| ntohs(fsmh.length))); | |
| } | |
| |
|
| auth->id = fsmh.id; | switch (proto) { |
| auth->code = fsmh.code; | case PROTO_PAP: |
| /* Status defaults to undefined */ | PapInput(l, auth, pkt, len); |
| auth->status = AUTH_STATUS_UNDEF; | break; |
| | case PROTO_CHAP: |
| switch (proto) { | ChapInput(l, auth, pkt, len); |
| case PROTO_PAP: | break; |
| PapInput(l, auth, pkt, len); | case PROTO_EAP: |
| break; | EapInput(l, auth, pkt, len); |
| case PROTO_CHAP: | break; |
| ChapInput(l, auth, pkt, len); | default: |
| break; | assert(0); |
| case PROTO_EAP: | } |
| EapInput(l, auth, pkt, len); | |
| break; | mbfree(bp); |
| default: | |
| assert(0); | |
| } | |
| | |
| mbfree(bp); | |
| } |
} |
| |
|
| /* |
/* |
|
Line 506 AuthInput(Link l, int proto, Mbuf bp)
|
Line 535 AuthInput(Link l, int proto, Mbuf bp)
|
| |
|
| void |
void |
| AuthOutput(Link l, int proto, u_int code, u_int id, const u_char *ptr, |
AuthOutput(Link l, int proto, u_int code, u_int id, const u_char *ptr, |
| int len, int add_len, u_char eap_type) | int len, int add_len, u_char eap_type) |
| { |
{ |
| struct fsmheader lh; | struct fsmheader lh; |
| Mbuf bp; | Mbuf bp; |
| int plen; | int plen; |
| char buf[32]; | char buf[32]; |
| |
|
| add_len = !!add_len; | add_len = !!add_len; |
| /* Setup header */ | /* Setup header */ |
| if (proto == PROTO_EAP) | if (proto == PROTO_EAP) |
| plen = sizeof(lh) + len + add_len + 1; | plen = sizeof(lh) + len + add_len + 1; |
| else | else |
| plen = sizeof(lh) + len + add_len; | plen = sizeof(lh) + len + add_len; |
| lh.code = code; | lh.code = code; |
| lh.id = id; | lh.id = id; |
| lh.length = htons(plen); | lh.length = htons(plen); |
| |
|
| /* Build packet */ | /* Build packet */ |
| bp = mbcopyback(NULL, 0, &lh, sizeof(lh)); | bp = mbcopyback(NULL, 0, &lh, sizeof(lh)); |
| if (proto == PROTO_EAP) | if (proto == PROTO_EAP) |
| bp = mbcopyback(bp, MBLEN(bp), &eap_type, 1); | bp = mbcopyback(bp, MBLEN(bp), &eap_type, 1); |
| if (add_len) { | if (add_len) { |
| u_char tl = len; | u_char tl = len; |
| bp = mbcopyback(bp, MBLEN(bp), &tl, 1); | |
| } | |
| bp = mbcopyback(bp, MBLEN(bp), ptr, len); | |
| |
|
| if (proto == PROTO_EAP) { | bp = mbcopyback(bp, MBLEN(bp), &tl, 1); |
| Log(LG_AUTH, ("[%s] %s: sending %s #%d len: %d, type: %s", l->name, | } |
| ProtoName(proto), AuthCode(proto, code, buf, sizeof(buf)), id, plen, EapType(eap_type))); | bp = mbcopyback(bp, MBLEN(bp), ptr, len); |
| } else { | |
| Log(LG_AUTH, ("[%s] %s: sending %s #%d len: %d", l->name, | |
| ProtoName(proto), AuthCode(proto, code, buf, sizeof(buf)), id, plen)); | |
| } | |
| |
|
| /* Send it out */ | if (proto == PROTO_EAP) { |
| NgFuncWritePppFrameLink(l, proto, bp); | Log(LG_AUTH, ("[%s] %s: sending %s #%d len: %d, type: %s", l->name, |
| | ProtoName(proto), AuthCode(proto, code, buf, sizeof(buf)), id, plen, EapType(eap_type))); |
| | } else { |
| | Log(LG_AUTH, ("[%s] %s: sending %s #%d len: %d", l->name, |
| | ProtoName(proto), AuthCode(proto, code, buf, sizeof(buf)), id, plen)); |
| | } |
| | |
| | /* Send it out */ |
| | NgFuncWritePppFrameLink(l, proto, bp); |
| } |
} |
| |
|
| /* |
/* |
|
Line 554 AuthOutput(Link l, int proto, u_int code, u_int id, co
|
Line 584 AuthOutput(Link l, int proto, u_int code, u_int id, co
|
| void |
void |
| AuthFinish(Link l, int which, int ok) |
AuthFinish(Link l, int which, int ok) |
| { |
{ |
| Auth const a = &l->lcp.auth; | Auth const a = &l->lcp.auth; |
| |
|
| if (which == AUTH_SELF_TO_PEER) | if (which == AUTH_SELF_TO_PEER) |
| a->self_to_peer = 0; | a->self_to_peer = 0; |
| else | else |
| a->peer_to_self = 0; | a->peer_to_self = 0; |
| /* Did auth fail (in either direction)? */ | /* Did auth fail (in either direction)? */ |
| if (!ok) { | if (!ok) { |
| AuthStop(l); | AuthStop(l); |
| LcpAuthResult(l, FALSE); | LcpAuthResult(l, FALSE); |
| return; | return; |
| } | } |
| /* Did auth succeed (in both directions)? */ | /* Did auth succeed (in both directions)? */ |
| if (!a->peer_to_self && !a->self_to_peer) { | if (!a->peer_to_self && !a->self_to_peer) { |
| AuthStop(l); | AuthStop(l); |
| LcpAuthResult(l, TRUE); | LcpAuthResult(l, TRUE); |
| return; | return; |
| } | } |
| } |
} |
| |
|
| /* |
/* |
|
Line 583 AuthFinish(Link l, int which, int ok)
|
Line 613 AuthFinish(Link l, int which, int ok)
|
| void |
void |
| AuthCleanup(Link l) |
AuthCleanup(Link l) |
| { |
{ |
| Auth a = &l->lcp.auth; | Auth a = &l->lcp.auth; |
| |
|
| Log(LG_AUTH2, ("[%s] AUTH: Cleanup", l->name)); | Log(LG_AUTH2, ("[%s] AUTH: Cleanup", l->name)); |
| |
|
| authparamsDestroy(&a->params); | authparamsDestroy(&a->params); |
| |
|
| l->session_id[0] = 0; | l->session_id[0] = 0; |
| } |
} |
| |
|
| /* | /* |
| * AuthDataNew() |
* AuthDataNew() |
| * |
* |
| * Create a new auth-data object |
* Create a new auth-data object |
| */ |
*/ |
| |
|
| AuthData |
AuthData |
| AuthDataNew(Link l) | AuthDataNew(Link l) |
| { |
{ |
| AuthData auth; | AuthData auth; |
| Auth a = &l->lcp.auth; | Auth a = &l->lcp.auth; |
| |
|
| auth = Malloc(MB_AUTH, sizeof(*auth)); | auth = Malloc(MB_AUTH, sizeof(*auth)); |
| auth->reply_message = NULL; | auth->reply_message = NULL; |
| auth->mschap_error = NULL; | auth->mschap_error = NULL; |
| auth->mschapv2resp = NULL; | auth->mschapv2resp = NULL; |
| auth->conf = l->lcp.auth.conf; | auth->conf = l->lcp.auth.conf; |
| if (l->lcp.auth.conf.extauth_script) | if (l->lcp.auth.conf.extauth_script) |
| auth->conf.extauth_script = Mstrdup(MB_AUTH, l->lcp.auth.conf.extauth_script); | auth->conf.extauth_script = Mstrdup(MB_AUTH, l->lcp.auth.conf.extauth_script); |
| if (l->lcp.auth.conf.extacct_script) | if (l->lcp.auth.conf.extacct_script) |
| auth->conf.extacct_script = Mstrdup(MB_AUTH, l->lcp.auth.conf.extacct_script); | auth->conf.extacct_script = Mstrdup(MB_AUTH, l->lcp.auth.conf.extacct_script); |
| |
|
| strlcpy(auth->info.lnkname, l->name, sizeof(auth->info.lnkname)); | strlcpy(auth->info.lnkname, l->name, sizeof(auth->info.lnkname)); |
| strlcpy(auth->info.msession_id, l->msession_id, sizeof(auth->info.msession_id)); | strlcpy(auth->info.msession_id, l->msession_id, sizeof(auth->info.msession_id)); |
| strlcpy(auth->info.session_id, l->session_id, sizeof(auth->info.session_id)); | strlcpy(auth->info.session_id, l->session_id, sizeof(auth->info.session_id)); |
| strlcpy(auth->info.peer_ident, l->lcp.peer_ident, sizeof(l->lcp.peer_ident)); | strlcpy(auth->info.peer_ident, l->lcp.peer_ident, sizeof(l->lcp.peer_ident)); |
| auth->info.originate = l->originate; | auth->info.originate = l->originate; |
| auth->info.downReason = NULL; | auth->info.downReason = NULL; |
| |
|
| if (l->bund) { | if (l->bund) { |
| strlcpy(auth->info.ifname, l->bund->iface.ifname, sizeof(auth->info.ifname)); | strlcpy(auth->info.ifname, l->bund->iface.ifname, sizeof(auth->info.ifname)); |
| auth->info.ifindex = l->bund->iface.ifindex; | auth->info.ifindex = l->bund->iface.ifindex; |
| strlcpy(auth->info.bundname, l->bund->name, sizeof(auth->info.bundname)); | strlcpy(auth->info.bundname, l->bund->name, sizeof(auth->info.bundname)); |
| auth->info.n_links = l->bund->n_links; | auth->info.n_links = l->bund->n_links; |
| auth->info.peer_addr = l->bund->ipcp.peer_addr; | auth->info.peer_addr = l->bund->ipcp.peer_addr; |
| } | bcopy(&auth->info.peer_addr6, &l->bund->ipv6cp.peer_addr, sizeof(struct in6_addr)); |
| | } |
| | /* Copy current link statistics */ |
| | memcpy(&auth->info.stats, &l->stats, sizeof(auth->info.stats)); |
| |
|
| /* Copy current link statistics */ |
|
| memcpy(&auth->info.stats, &l->stats, sizeof(auth->info.stats)); |
|
| |
|
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| /* If it is present copy services statistics */ | /* If it is present copy services statistics */ |
| if (l->bund) { | if (l->bund) { |
| IfaceGetStats(l->bund, &auth->info.ss); | IfaceGetStats(l->bund, &auth->info.ss); |
| IfaceAddStats(&auth->info.ss, &l->bund->iface.prevstats); | IfaceAddStats(&auth->info.ss, &l->bund->iface.prevstats); |
| } | } |
| #endif |
#endif |
| |
|
| if (l->downReasonValid) | if (l->downReasonValid) |
| auth->info.downReason = Mstrdup(MB_AUTH, l->downReason); | auth->info.downReason = Mstrdup(MB_AUTH, l->downReason); |
| |
|
| auth->info.last_up = l->last_up; | auth->info.last_up = l->last_up; |
| auth->info.phys_type = l->type; | auth->info.phys_type = l->type; |
| auth->info.linkID = l->id; | auth->info.linkID = l->id; |
| |
|
| authparamsCopy(&a->params,&auth->params); | authparamsCopy(&a->params, &auth->params); |
| |
|
| return auth; | return auth; |
| } |
} |
| |
|
| /* |
/* |
|
Line 661 AuthDataNew(Link l)
|
Line 691 AuthDataNew(Link l)
|
| void |
void |
| AuthDataDestroy(AuthData auth) |
AuthDataDestroy(AuthData auth) |
| { |
{ |
| authparamsDestroy(&auth->params); | authparamsDestroy(&auth->params); |
| Freee(auth->info.downReason); | Freee(auth->info.downReason); |
| Freee(auth->reply_message); | Freee(auth->reply_message); |
| Freee(auth->mschap_error); | Freee(auth->mschap_error); |
| Freee(auth->mschapv2resp); | Freee(auth->mschapv2resp); |
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| IfaceFreeStats(&auth->info.ss); | IfaceFreeStats(&auth->info.ss); |
| #endif |
#endif |
| Freee(auth->conf.extauth_script); | Freee(auth->conf.extauth_script); |
| Freee(auth->conf.extacct_script); | Freee(auth->conf.extacct_script); |
| Freee(auth); | Freee(auth); |
| } |
} |
| |
|
| /* |
/* |
|
Line 683 AuthDataDestroy(AuthData auth)
|
Line 713 AuthDataDestroy(AuthData auth)
|
| void |
void |
| AuthStop(Link l) |
AuthStop(Link l) |
| { |
{ |
| Auth a = &l->lcp.auth; | Auth a = &l->lcp.auth; |
| |
|
| TimerStop(&a->timer); | TimerStop(&a->timer); |
| PapStop(&a->pap); | PapStop(&a->pap); |
| ChapStop(&a->chap); | ChapStop(&a->chap); |
| EapStop(&a->eap); | EapStop(&a->eap); |
| paction_cancel(&a->thread); | paction_cancel(&a->thread); |
| } |
} |
| |
|
| /* |
/* |
|
Line 697 AuthStop(Link l)
|
Line 727 AuthStop(Link l)
|
| * |
* |
| * Show auth stats |
* Show auth stats |
| */ |
*/ |
| | |
| int |
int |
| AuthStat(Context ctx, int ac, char *av[], void *arg) | AuthStat(Context ctx, int ac, const char *const av[], const void *arg) |
| { |
{ |
| Auth const au = &ctx->lnk->lcp.auth; | Auth const au = &ctx->lnk->lcp.auth; |
| AuthConf const conf = &au->conf; | AuthConf const conf = &au->conf; |
| char buf[48], buf2[16]; | char buf[48], buf2[16]; |
| | |
| #if defined(USE_IPFW) || defined(USE_NG_BPF) |
#if defined(USE_IPFW) || defined(USE_NG_BPF) |
| struct acl *a; | struct acl *a; |
| | |
| #endif |
#endif |
| IfaceRoute r; | IfaceRoute r; |
| | |
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| int k; | int k; |
| | |
| #endif |
#endif |
| |
|
| Printf("Configuration:\r\n"); | (void)ac; |
| Printf("\tMy authname : %s\r\n", conf->authname); | (void)av; |
| Printf("\tMax-Logins : %d%s\r\n", gMaxLogins, (gMaxLoginsCI?" CI":"")); | (void)arg; |
| Printf("\tAcct Update : %d\r\n", conf->acct_update); | |
| Printf("\t Limit In : %d\r\n", conf->acct_update_lim_recv); | |
| Printf("\t Limit Out : %d\r\n", conf->acct_update_lim_xmit); | |
| Printf("\tAuth timeout : %d\r\n", conf->timeout); | |
| Printf("\tExtAuth script : %s\r\n", conf->extauth_script?conf->extauth_script:""); | |
| Printf("\tExtAcct script : %s\r\n", conf->extacct_script?conf->extacct_script:""); | |
| | |
| Printf("Auth options\r\n"); | |
| OptStat(ctx, &conf->options, gConfList); | |
| |
|
| Printf("Auth Data\r\n"); | Printf("Configuration:\r\n"); |
| Printf("\tPeer authname : %s\r\n", au->params.authname); | Printf("\tMy authname : %s\r\n", conf->authname); |
| Printf("\tInterface name : %s\r\n", au->params.ifname); | Printf("\tMax-Logins : %u%s\r\n", gMaxLogins, (gMaxLoginsCI ? " CI" : "")); |
| | Printf("\tAcct Update : %d\r\n", conf->acct_update); |
| | Printf("\t Limit In : %d\r\n", conf->acct_update_lim_recv); |
| | Printf("\t Limit Out : %d\r\n", conf->acct_update_lim_xmit); |
| | Printf("\tAuth timeout : %d\r\n", conf->timeout); |
| | Printf("\tExtAuth script : %s\r\n", conf->extauth_script ? conf->extauth_script : ""); |
| | Printf("\tExtAcct script : %s\r\n", conf->extacct_script ? conf->extacct_script : ""); |
| | |
| | Printf("Auth options\r\n"); |
| | OptStat(ctx, &conf->options, gConfList); |
| | |
| | Printf("Auth Data\r\n"); |
| | Printf("\tPeer authname : %s\r\n", au->params.authname); |
| | Printf("\tInterface name : %s\r\n", au->params.ifname); |
| #ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
| Printf("\tInterface descr.: \"%s\"\r\n", | Printf("\tInterface descr.: \"%s\"\r\n", |
| au->params.ifdescr != NULL ? au->params.ifdescr : "<none>"); | au->params.ifdescr != NULL ? au->params.ifdescr : "<none>"); |
| #endif |
#endif |
| #ifdef SIOCAIFGROUP |
#ifdef SIOCAIFGROUP |
| Printf("\tInterface group : %s\r\n", au->params.ifgroup); | Printf("\tInterface group : %s\r\n", au->params.ifgroup); |
| #endif |
#endif |
| Printf("\tIP range : %s\r\n", (au->params.range_valid)? | Printf("\tIP range : %s\r\n", (au->params.range_valid) ? |
| u_rangetoa(&au->params.range,buf,sizeof(buf)):""); | u_rangetoa(&au->params.range, buf, sizeof(buf)) : ""); |
| Printf("\tIP pool : %s\r\n", au->params.ippool); | Printf("\tIP pool : %s\r\n", au->params.ippool); |
| Printf("\tDNS : %s %s\r\n", | Printf("\tDNS : %s %s\r\n", |
| inet_ntop(AF_INET, &au->params.peer_dns[0], buf, sizeof(buf)), | inet_ntop(AF_INET, &au->params.peer_dns[0], buf, sizeof(buf)), |
| inet_ntop(AF_INET, &au->params.peer_dns[1], buf2, sizeof(buf2))); | inet_ntop(AF_INET, &au->params.peer_dns[1], buf2, sizeof(buf2))); |
| Printf("\tNBNS : %s %s\r\n", | Printf("\tNBNS : %s %s\r\n", |
| inet_ntop(AF_INET, &au->params.peer_nbns[0], buf, sizeof(buf)), | inet_ntop(AF_INET, &au->params.peer_nbns[0], buf, sizeof(buf)), |
| inet_ntop(AF_INET, &au->params.peer_nbns[1], buf2, sizeof(buf2))); | inet_ntop(AF_INET, &au->params.peer_nbns[1], buf2, sizeof(buf2))); |
| Printf("\tMTU : %u\r\n", au->params.mtu); | Printf("\tVJ Compression : %s\r\n", au->params.vjc_enable ? "yes" : "no"); |
| Printf("\tSession-Timeout : %u\r\n", au->params.session_timeout); | Printf("\tMTU : %u\r\n", au->params.mtu); |
| Printf("\tIdle-Timeout : %u\r\n", au->params.idle_timeout); | Printf("\tSession-Timeout : %u\r\n", au->params.session_timeout); |
| Printf("\tAcct-Update : %u\r\n", au->params.acct_update); | Printf("\tIdle-Timeout : %u\r\n", au->params.idle_timeout); |
| Printf("\tRoutes :\r\n"); | Printf("\tAcct-Update : %u\r\n", au->params.acct_update); |
| SLIST_FOREACH(r, &au->params.routes, next) { | Printf("\tRoutes :\r\n"); |
| Printf("\t\t%s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf))); | SLIST_FOREACH(r, &au->params.routes, next) { |
| } | Printf("\t\t%s\r\n", u_rangetoa(&r->dest, buf, sizeof(buf))); |
| | } |
| #ifdef USE_IPFW |
#ifdef USE_IPFW |
| Printf("\tIPFW rules :\r\n"); | Printf("\tIPFW rules :\r\n"); |
| a = au->params.acl_rule; | a = au->params.acl_rule; |
| while (a) { | while (a) { |
| Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule); | Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule); |
| a = a->next; | a = a->next; |
| } | |
| Printf("\tIPFW pipes :\r\n"); | |
| a = au->params.acl_pipe; | |
| while (a) { | |
| Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule); | |
| a = a->next; | |
| } | |
| Printf("\tIPFW queues :\r\n"); | |
| a = au->params.acl_queue; | |
| while (a) { | |
| Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule); | |
| a = a->next; | |
| } | |
| Printf("\tIPFW tables :\r\n"); | |
| a = au->params.acl_table; | |
| while (a) { | |
| if (a->number != 0) | |
| Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule); | |
| else | |
| Printf("\t\t#%d\t: '%s'\r\n", a->real_number, a->rule); | |
| a = a->next; | |
| } | |
| #endif /* USE_IPFW */ | |
| #ifdef USE_NG_BPF | |
| Printf("\tTraffic filters :\r\n"); | |
| for (k = 0; k < ACL_FILTERS; k++) { | |
| a = au->params.acl_filters[k]; | |
| while (a) { | |
| Printf("\t%d#%d\t: '%s'\r\n", (k + 1), a->number, a->rule); | |
| a = a->next; | |
| } |
} |
| } | Printf("\tIPFW pipes :\r\n"); |
| Printf("\tTraffic limits :\r\n"); | a = au->params.acl_pipe; |
| for (k = 0; k < 2; k++) { | |
| a = au->params.acl_limits[k]; | |
| while (a) { |
while (a) { |
| Printf("\t\t%s#%d%s%s\t: '%s'\r\n", (k?"out":"in"), a->number, | Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule); |
| ((a->name[0])?"#":""), a->name, a->rule); | a = a->next; |
| a = a->next; | |
| } |
} |
| } | Printf("\tIPFW queues :\r\n"); |
| #endif /* USE_NG_BPF */ | a = au->params.acl_queue; |
| Printf("\tMS-Domain : %s\r\n", au->params.msdomain); | while (a) { |
| Printf("\tMPPE Types : %s\r\n", AuthMPPEPolicyname(au->params.msoft.policy)); | Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule); |
| Printf("\tMPPE Policy : %s\r\n", AuthMPPETypesname(au->params.msoft.types, buf, sizeof(buf))); | a = a->next; |
| Printf("\tMPPE Keys : %s\r\n", au->params.msoft.has_keys ? "yes" : "no"); | } |
| | Printf("\tIPFW tables :\r\n"); |
| | a = au->params.acl_table; |
| | while (a) { |
| | if (a->number != 0) |
| | Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule); |
| | else |
| | Printf("\t\t#%d\t: '%s'\r\n", a->real_number, a->rule); |
| | a = a->next; |
| | } |
| | #endif /* USE_IPFW */ |
| | #ifdef USE_NG_BPF |
| | Printf("\tTraffic filters :\r\n"); |
| | for (k = 0; k < ACL_FILTERS; k++) { |
| | a = au->params.acl_filters[k]; |
| | while (a) { |
| | Printf("\t%d#%d\t: '%s'\r\n", (k + 1), a->number, a->rule); |
| | a = a->next; |
| | } |
| | } |
| | Printf("\tTraffic limits :\r\n"); |
| | for (k = 0; k < 2; k++) { |
| | a = au->params.acl_limits[k]; |
| | while (a) { |
| | Printf("\t\t%s#%d%s%s\t: '%s'\r\n", (k ? "out" : "in"), a->number, |
| | ((a->name[0]) ? "#" : ""), a->name, a->rule); |
| | a = a->next; |
| | } |
| | } |
| | #endif /* USE_NG_BPF */ |
| | Printf("\tMS-Domain : %s\r\n", au->params.msdomain); |
| | Printf("\tMPPE Types : %s\r\n", AuthMPPEPolicyname(au->params.msoft.policy)); |
| | Printf("\tMPPE Policy : %s\r\n", AuthMPPETypesname(au->params.msoft.types, buf, sizeof(buf))); |
| | Printf("\tMPPE Keys : %s\r\n", au->params.msoft.has_keys ? "yes" : "no"); |
| |
|
| return (0); | return (0); |
| } |
} |
| |
|
| |
|
| /* |
/* |
| * AuthAccount() |
* AuthAccount() |
| * |
* |
| * Accounting stuff, | * Accounting stuff, |
| */ |
*/ |
| | |
| void |
void |
| AuthAccountStart(Link l, int type) |
AuthAccountStart(Link l, int type) |
| { |
{ |
| Auth const a = &l->lcp.auth; | Auth const a = &l->lcp.auth; |
| AuthData auth; | AuthData auth; |
| | |
| /* maybe an outstanding thread is running */ | /* maybe an outstanding thread is running */ |
| if (a->acct_thread) { | if (a->acct_thread) { |
| if (type == AUTH_ACCT_START || type == AUTH_ACCT_STOP) { | if (type == AUTH_ACCT_START || type == AUTH_ACCT_STOP) { |
| paction_cancel(&a->acct_thread); | paction_cancel(&a->acct_thread); |
| } else { | } else { |
| Log(LG_AUTH2, ("[%s] ACCT: Accounting thread is already running", | Log(LG_AUTH2, ("[%s] ACCT: Accounting thread is already running", |
| l->name)); | l->name)); |
| return; | return; |
| | } |
| } |
} |
| } | LinkUpdateStats(l); |
| | if (type == AUTH_ACCT_STOP) { |
| | Log(LG_AUTH2, ("[%s] ACCT: Accounting data for user '%s': %lu seconds, %llu octets in, %llu octets out", |
| | l->name, a->params.authname, |
| | (unsigned long)(time(NULL) - l->last_up), |
| | (unsigned long long)l->stats.recvOctets, |
| | (unsigned long long)l->stats.xmitOctets)); |
| | } |
| | if (type == AUTH_ACCT_START) { |
| | u_int updateInterval; |
| |
|
| LinkUpdateStats(l); | if (a->params.acct_update > 0) |
| if (type == AUTH_ACCT_STOP) { | updateInterval = a->params.acct_update; |
| Log(LG_AUTH2, ("[%s] ACCT: Accounting data for user '%s': %lu seconds, %llu octets in, %llu octets out", | else |
| l->name, a->params.authname, | updateInterval = a->conf.acct_update; |
| (unsigned long) (time(NULL) - l->last_up), | |
| (unsigned long long)l->stats.recvOctets, | |
| (unsigned long long)l->stats.xmitOctets)); | |
| } | |
| |
|
| if (type == AUTH_ACCT_START) { | if (updateInterval > 0) { |
| u_int updateInterval; | /* Save initial statistics. */ |
| | memcpy(&a->prev_stats, &l->stats, |
| if (a->params.acct_update > 0) | sizeof(a->prev_stats)); |
| updateInterval = a->params.acct_update; | |
| else | |
| updateInterval = a->conf.acct_update; | |
| |
|
| if (updateInterval > 0) { | /* Start accounting update timer. */ |
| /* Save initial statistics. */ | TimerInit(&a->acct_timer, "AuthAccountTimer", |
| memcpy(&a->prev_stats, &l->stats, | updateInterval * SECONDS, AuthAccountTimeout, l); |
| sizeof(a->prev_stats)); | TimerStartRecurring(&a->acct_timer); |
| } |
| /* Start accounting update timer. */ | |
| TimerInit(&a->acct_timer, "AuthAccountTimer", | |
| updateInterval * SECONDS, AuthAccountTimeout, l); | |
| TimerStartRecurring(&a->acct_timer); | |
| } |
} |
| } | if (type == AUTH_ACCT_UPDATE) { |
| | /* |
| if (type == AUTH_ACCT_UPDATE) { | * Suppress sending of accounting update, if byte threshold |
| /* | * is configured, and delta since last update doesn't exceed it. |
| * Suppress sending of accounting update, if byte threshold | */ |
| * is configured, and delta since last update doesn't exceed it. | u_int lim_recv, lim_xmit; |
| */ | |
| u_int lim_recv, lim_xmit; | |
| |
|
| if (a->params.acct_update_lim_recv > 0) | if (a->params.acct_update_lim_recv > 0) |
| lim_recv = a->params.acct_update_lim_recv; | lim_recv = a->params.acct_update_lim_recv; |
| else | else |
| lim_recv = a->conf.acct_update_lim_recv; | lim_recv = a->conf.acct_update_lim_recv; |
| if (a->params.acct_update_lim_xmit > 0) | if (a->params.acct_update_lim_xmit > 0) |
| lim_xmit = a->params.acct_update_lim_xmit; | lim_xmit = a->params.acct_update_lim_xmit; |
| else | else |
| lim_xmit = a->conf.acct_update_lim_xmit; | lim_xmit = a->conf.acct_update_lim_xmit; |
| if (lim_recv > 0 || lim_xmit > 0) { | if (lim_recv > 0 || lim_xmit > 0) { |
| if ((l->stats.recvOctets - a->prev_stats.recvOctets < lim_recv) && | if ((l->stats.recvOctets - a->prev_stats.recvOctets < lim_recv) && |
| (l->stats.xmitOctets - a->prev_stats.xmitOctets < lim_xmit)) { | (l->stats.xmitOctets - a->prev_stats.xmitOctets < lim_xmit)) { |
| Log(LG_AUTH2, ("[%s] ACCT: Shouldn't send Interim-Update", l->name)); | Log(LG_AUTH2, ("[%s] ACCT: Shouldn't send Interim-Update", l->name)); |
| return; | return; |
| } else { | } else { |
| /* Save current statistics. */ | /* Save current statistics. */ |
| memcpy(&a->prev_stats, &l->stats, sizeof(a->prev_stats)); | memcpy(&a->prev_stats, &l->stats, sizeof(a->prev_stats)); |
| } | } |
| | } |
| } |
} |
| } | if (type == AUTH_ACCT_STOP) { |
| | /* Stop accounting update timer if running. */ |
| if (type == AUTH_ACCT_STOP) { | TimerStop(&a->acct_timer); |
| /* Stop accounting update timer if running. */ | } |
| TimerStop(&a->acct_timer); | if (Enabled(&a->conf.options, AUTH_CONF_RADIUS_ACCT) || |
| } | |
| |
| if (Enabled(&a->conf.options, AUTH_CONF_RADIUS_ACCT) || | |
| #ifdef USE_PAM |
#ifdef USE_PAM |
| Enabled(&a->conf.options, AUTH_CONF_PAM_ACCT) || | Enabled(&a->conf.options, AUTH_CONF_PAM_ACCT) || |
| #endif |
#endif |
| #ifdef USE_SYSTEM |
#ifdef USE_SYSTEM |
| Enabled(&a->conf.options, AUTH_CONF_SYSTEM_ACCT) || | Enabled(&a->conf.options, AUTH_CONF_SYSTEM_ACCT) || |
| #endif |
#endif |
| Enabled(&a->conf.options, AUTH_CONF_EXT_ACCT)) { | Enabled(&a->conf.options, AUTH_CONF_EXT_ACCT)) { |
| | |
| auth = AuthDataNew(l); | |
| auth->acct_type = type; | |
| |
|
| if (paction_start(&a->acct_thread, &gGiantMutex, AuthAccount, | auth = AuthDataNew(l); |
| AuthAccountFinish, auth) == -1) { | auth->acct_type = type; |
| Perror("[%s] ACCT: Couldn't start thread", l->name); | |
| AuthDataDestroy(auth); | |
| } | |
| } | |
| |
|
| |
if (paction_start(&a->acct_thread, &gGiantMutex, AuthAccount, |
| |
AuthAccountFinish, auth) == -1) { |
| |
Perror("[%s] ACCT: Couldn't start thread", l->name); |
| |
AuthDataDestroy(auth); |
| |
} |
| |
} |
| } |
} |
| |
|
| /* |
/* |
|
Line 919 AuthAccountStart(Link l, int type)
|
Line 952 AuthAccountStart(Link l, int type)
|
| * |
* |
| * Timer function for accounting updates |
* Timer function for accounting updates |
| */ |
*/ |
| | |
| void |
void |
| AuthAccountTimeout(void *arg) |
AuthAccountTimeout(void *arg) |
| { |
{ |
| Link l = (Link)arg; | Link l = (Link) arg; |
| | |
| Log(LG_AUTH2, ("[%s] ACCT: Time for Accounting Update", | |
| l->name)); | |
| |
|
| AuthAccountStart(l, AUTH_ACCT_UPDATE); | Log(LG_AUTH2, ("[%s] ACCT: Time for Accounting Update", |
| | l->name)); |
| | |
| | AuthAccountStart(l, AUTH_ACCT_UPDATE); |
| } |
} |
| |
|
| /* |
/* |
|
Line 937 AuthAccountTimeout(void *arg)
|
Line 970 AuthAccountTimeout(void *arg)
|
| * Asynchr. accounting handler, called from a paction. |
* Asynchr. accounting handler, called from a paction. |
| * NOTE: Thread safety is needed here |
* NOTE: Thread safety is needed here |
| */ |
*/ |
| | |
| static void |
static void |
| AuthAccount(void *arg) |
AuthAccount(void *arg) |
| { |
{ |
| AuthData const auth = (AuthData)arg; | AuthData const auth = (AuthData) arg; |
| int err = 0; | int err = 0; |
| | |
| Log(LG_AUTH2, ("[%s] ACCT: Thread started", auth->info.lnkname)); | Log(LG_AUTH2, ("[%s] ACCT: Thread started", auth->info.lnkname)); |
| | |
| if (Enabled(&auth->conf.options, AUTH_CONF_RADIUS_ACCT)) | if (Enabled(&auth->conf.options, AUTH_CONF_RADIUS_ACCT)) |
| err |= RadiusAccount(auth); | err |= RadiusAccount(auth); |
| #ifdef USE_PAM |
#ifdef USE_PAM |
| if (Enabled(&auth->conf.options, AUTH_CONF_PAM_ACCT)) | if (Enabled(&auth->conf.options, AUTH_CONF_PAM_ACCT)) |
| err |= AuthPAMAcct(auth); | err |= AuthPAMAcct(auth); |
| #endif |
#endif |
| #ifdef USE_SYSTEM |
#ifdef USE_SYSTEM |
| if (Enabled(&auth->conf.options, AUTH_CONF_SYSTEM_ACCT)) | if (Enabled(&auth->conf.options, AUTH_CONF_SYSTEM_ACCT)) |
| err |= AuthSystemAcct(auth); | err |= AuthSystemAcct(auth); |
| #endif |
#endif |
| if (Enabled(&auth->conf.options, AUTH_CONF_EXT_ACCT)) | if (Enabled(&auth->conf.options, AUTH_CONF_EXT_ACCT)) |
| err |= AuthExternalAcct(auth); | err |= AuthExternalAcct(auth); |
| | |
| if (err != 0 && auth->acct_type == AUTH_ACCT_START && | if (err != 0 && auth->acct_type == AUTH_ACCT_START && |
| Enabled(&auth->conf.options, AUTH_CONF_ACCT_MANDATORY)) { |
Enabled(&auth->conf.options, AUTH_CONF_ACCT_MANDATORY)) { |
| Log(LG_AUTH, ("[%s] ACCT: Close link due to accounting start error", | Log(LG_AUTH, ("[%s] ACCT: Close link due to accounting start error", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| auth->drop_user = 1; | auth->drop_user = 1; |
| } | } |
| } |
} |
| |
|
| /* |
/* |
| * AuthAccountFinish |
* AuthAccountFinish |
| * | * |
| * Return point for the accounting thread() |
* Return point for the accounting thread() |
| */ |
*/ |
| | |
| static void |
static void |
| AuthAccountFinish(void *arg, int was_canceled) |
AuthAccountFinish(void *arg, int was_canceled) |
| { |
{ |
| AuthData auth = (AuthData)arg; | AuthData auth = (AuthData) arg; |
| Link l; | Link l; |
| |
|
| if (was_canceled) { | if (was_canceled) { |
| Log(LG_AUTH2, ("[%s] ACCT: Thread was canceled", | Log(LG_AUTH2, ("[%s] ACCT: Thread was canceled", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| } else { | } else { |
| Log(LG_AUTH2, ("[%s] ACCT: Thread finished normally", | Log(LG_AUTH2, ("[%s] ACCT: Thread finished normally", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| } | } |
| | |
| /* Cleanup */ | |
| RadiusClose(auth); | |
| |
|
| if (was_canceled) { | /* Cleanup */ |
| AuthDataDestroy(auth); | RadiusClose(auth); |
| return; | |
| } | |
| | |
| l = gLinks[auth->info.linkID]; | |
| if (l == NULL) { | |
| AuthDataDestroy(auth); | |
| return; | |
| } | |
| |
|
| if (auth->drop_user && auth->acct_type != AUTH_ACCT_STOP) { | if (was_canceled) { |
| Log(LG_AUTH, ("[%s] ACCT: Link close requested by the accounting", | AuthDataDestroy(auth); |
| l->name)); | return; |
| RecordLinkUpDownReason(NULL, l, 0, STR_MANUALLY, NULL); | } |
| LinkClose(l); | l = gLinks[auth->info.linkID]; |
| } | if (l == NULL) { |
| AuthDataDestroy(auth); | AuthDataDestroy(auth); |
| LinkShutdownCheck(l, l->lcp.fsm.state); | return; |
| | } |
| | if (auth->drop_user && auth->acct_type != AUTH_ACCT_STOP) { |
| | Log(LG_AUTH, ("[%s] ACCT: Link close requested by the accounting", |
| | l->name)); |
| | RecordLinkUpDownReason(NULL, l, 0, STR_MANUALLY, NULL); |
| | LinkClose(l); |
| | } |
| | AuthDataDestroy(auth); |
| | LinkShutdownCheck(l, l->lcp.fsm.state); |
| } |
} |
| |
|
| /* |
/* |
|
Line 1018 AuthAccountFinish(void *arg, int was_canceled)
|
Line 1049 AuthAccountFinish(void *arg, int was_canceled)
|
| */ |
*/ |
| |
|
| int |
int |
| AuthGetData(char *authname, char *password, size_t passlen, | AuthGetData(char *authname, char *password, size_t passlen, |
| struct u_range *range, u_char *range_valid) |
struct u_range *range, u_char *range_valid) |
| { |
{ |
| FILE *fp; | FILE *fp; |
| int ac; | int ac; |
| char *av[20]; | char *av[20]; |
| char *line; | char *line; |
| |
|
| /* Check authname, must be non-empty */ | /* Check authname, must be non-empty */ |
| if (authname == NULL || authname[0] == 0) { | if (authname == NULL || authname[0] == 0) { |
| return(-1); | return (-1); |
| } | |
| |
| /* Search secrets file */ | |
| if ((fp = OpenConfFile(SECRET_FILE, NULL)) == NULL) | |
| return(-1); | |
| while ((line = ReadFullLine(fp, NULL, NULL, 0)) != NULL) { | |
| memset(av, 0, sizeof(av)); | |
| ac = ParseLine(line, av, sizeof(av) / sizeof(*av), 1); | |
| Freee(line); | |
| if (ac >= 2 | |
| && (strcmp(av[0], authname) == 0 | |
| || (av[1][0] == '!' && strcmp(av[0], "*") == 0))) { | |
| if (av[1][0] == '!') { /* external auth program */ | |
| if (AuthGetExternalPassword((av[1]+1), | |
| authname, password, passlen) == -1) { | |
| FreeArgs(ac, av); | |
| fclose(fp); | |
| return(-1); | |
| } |
} |
| } else { | /* Search secrets file */ |
| strlcpy(password, av[1], passlen); | if ((fp = OpenConfFile(SECRET_FILE, NULL)) == NULL) |
| } | return (-1); |
| if (range != NULL && range_valid != NULL) { | while ((line = ReadFullLine(fp, NULL, NULL, 0)) != NULL) { |
| u_rangeclear(range); | memset(av, 0, sizeof(av)); |
| if (ac >= 3) | ac = ParseLine(line, av, sizeof(av) / sizeof(*av), 1); |
| *range_valid = ParseRange(av[2], range, ALLOW_IPV4); | Freee(line); |
| else | if (ac >= 2 |
| *range_valid = FALSE; | && (strcmp(av[0], authname) == 0 |
| } | || (av[1][0] == '!' && strcmp(av[0], "*") == 0))) { |
| FreeArgs(ac, av); | if (av[1][0] == '!') { /* external auth program */ |
| fclose(fp); | if (AuthGetExternalPassword((av[1] + 1), |
| return(0); | authname, password, passlen) == -1) { |
| } | FreeArgs(ac, av); |
| FreeArgs(ac, av); | fclose(fp); |
| } | return (-1); |
| fclose(fp); | } |
| | } else { |
| | strlcpy(password, av[1], passlen); |
| | } |
| | if (range != NULL && range_valid != NULL) { |
| | u_rangeclear(range); |
| | if (ac >= 3) |
| | *range_valid = ParseRange(av[2], range, ALLOW_IPV4); |
| | else |
| | *range_valid = FALSE; |
| | } |
| | FreeArgs(ac, av); |
| | fclose(fp); |
| | return (0); |
| | } |
| | FreeArgs(ac, av); |
| | } |
| | fclose(fp); |
| |
|
| return(-1); /* Invalid */ | return (-1); /* Invalid */ |
| } |
} |
| |
|
| /* |
/* |
|
Line 1075 AuthGetData(char *authname, char *password, size_t pas
|
Line 1105 AuthGetData(char *authname, char *password, size_t pas
|
| * Starts the Auth-Thread |
* Starts the Auth-Thread |
| */ |
*/ |
| |
|
| void | void |
| AuthAsyncStart(Link l, AuthData auth) |
AuthAsyncStart(Link l, AuthData auth) |
| { |
{ |
| Auth const a = &l->lcp.auth; | Auth const a = &l->lcp.auth; |
| const char *rept; | const char *rept; |
| | |
| /* Check link action */ | /* Check link action */ |
| rept = LinkMatchAction(l, 2, auth->params.authname); | rept = LinkMatchAction(l, 2, auth->params.authname); |
| if (rept) { | if (rept) { |
| if (strcmp(rept,"##DROP##") == 0) { | if (strcmp(rept, "##DROP##") == 0) { |
| /* Action told we must drop this connection */ | /* Action told we must drop this connection */ |
| Log(LG_AUTH, ("[%s] Drop connection", l->name)); | Log(LG_AUTH, ("[%s] Drop connection", l->name)); |
| PhysClose(l); | PhysClose(l); |
| AuthDataDestroy(auth); | AuthDataDestroy(auth); |
| return; | return; |
| | } |
| | /* Action told we must forward this connection */ |
| | if (RepCreate(l, rept)) { |
| | Log(LG_ERR, ("[%s] Repeater to \"%s\" creation error", l->name, rept)); |
| | PhysClose(l); |
| | AuthDataDestroy(auth); |
| | return; |
| | } |
| | /* Create repeater */ |
| | RepIncoming(l); |
| | /* Reconnect link netgraph hook to repeater */ |
| | LinkNgToRep(l); |
| | /* Kill the LCP */ |
| | LcpDown(l); |
| | LcpClose(l); |
| | AuthDataDestroy(auth); |
| | return; |
| } |
} |
| | /* Check if we are ready to process request. */ |
| /* Action told we must forward this connection */ | if (a->thread) { |
| if (RepCreate(l, rept)) { | auth->status = AUTH_STATUS_BUSY; |
| Log(LG_ERR, ("[%s] Repeater to \"%s\" creation error", l->name, rept)); | auth->finish(l, auth); |
| PhysClose(l); | return; |
| AuthDataDestroy(auth); | |
| return; | |
| } |
} |
| /* Create repeater */ | /* perform pre authentication checks (single-login, etc.) */ |
| RepIncoming(l); | if (AuthPreChecks(auth) < 0) { |
| /* Reconnect link netgraph hook to repeater */ | Log(LG_AUTH, ("[%s] AUTH: AuthPreCheck failed for \"%s\"", |
| LinkNgToRep(l); | l->name, auth->params.authname)); |
| /* Kill the LCP */ | auth->finish(l, auth); |
| LcpDown(l); | return; |
| LcpClose(l); | } |
| AuthDataDestroy(auth); | if (paction_start(&a->thread, &gGiantMutex, AuthAsync, |
| return; | AuthAsyncFinish, auth) == -1) { |
| } | Perror("[%s] AUTH: Couldn't start thread", l->name); |
| auth->status = AUTH_STATUS_FAIL; |
| /* Check if we are ready to process request. */ | auth->why_fail = AUTH_FAIL_NOT_EXPECTED; |
| if (a->thread) { | auth->finish(l, auth); |
| auth->status = AUTH_STATUS_BUSY; | } |
| auth->finish(l, auth); | |
| return; | |
| } | |
| | |
| /* perform pre authentication checks (single-login, etc.) */ | |
| if (AuthPreChecks(auth) < 0) { | |
| Log(LG_AUTH, ("[%s] AUTH: AuthPreCheck failed for \"%s\"", | |
| l->name, auth->params.authname)); | |
| auth->finish(l, auth); | |
| return; | |
| } | |
| |
| if (paction_start(&a->thread, &gGiantMutex, AuthAsync, | |
| AuthAsyncFinish, auth) == -1) { | |
| Perror("[%s] AUTH: Couldn't start thread", l->name); | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_NOT_EXPECTED; | |
| auth->finish(l, auth); | |
| } | |
| } |
} |
| |
|
| /* |
/* |
|
Line 1140 AuthAsyncStart(Link l, AuthData auth)
|
Line 1166 AuthAsyncStart(Link l, AuthData auth)
|
| * Asynchr. auth handler, called from a paction. |
* Asynchr. auth handler, called from a paction. |
| * NOTE: Thread safety is needed here |
* NOTE: Thread safety is needed here |
| */ |
*/ |
| | |
| static void |
static void |
| AuthAsync(void *arg) |
AuthAsync(void *arg) |
| { |
{ |
| AuthData const auth = (AuthData)arg; | AuthData const auth = (AuthData) arg; |
| |
|
| Log(LG_AUTH2, ("[%s] AUTH: Thread started", auth->info.lnkname)); | Log(LG_AUTH2, ("[%s] AUTH: Thread started", auth->info.lnkname)); |
| |
|
| if (Enabled(&auth->conf.options, AUTH_CONF_EXT_AUTH)) { | if (Enabled(&auth->conf.options, AUTH_CONF_EXT_AUTH)) { |
| auth->params.authentic = AUTH_CONF_EXT_AUTH; | auth->params.authentic = AUTH_CONF_EXT_AUTH; |
| Log(LG_AUTH, ("[%s] AUTH: Trying EXTERNAL", auth->info.lnkname)); | Log(LG_AUTH, ("[%s] AUTH: Trying EXTERNAL", auth->info.lnkname)); |
| if (AuthExternal(auth)) { | if (AuthExternal(auth)) { |
| Log(LG_AUTH, ("[%s] AUTH: EXTERNAL returned error", | Log(LG_ERR | LG_AUTH, ("[%s] AUTH: EXTERNAL returned error", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| } else { | } else { |
| Log(LG_AUTH, ("[%s] AUTH: EXTERNAL returned: %s", | Log(LG_AUTH, ("[%s] AUTH: EXTERNAL returned: %s", |
| auth->info.lnkname, AuthStatusText(auth->status))); | auth->info.lnkname, AuthStatusText(auth->status))); |
| if (auth->status == AUTH_STATUS_SUCCESS | if (auth->status == AUTH_STATUS_SUCCESS |
| || auth->status == AUTH_STATUS_UNDEF) | || auth->status == AUTH_STATUS_UNDEF) |
| | return; |
| | } |
| | } |
| | if (auth->proto == PROTO_EAP && auth->eap_radius) { |
| | auth->params.authentic = AUTH_CONF_RADIUS_AUTH; |
| | RadiusEapProxy(auth); |
| return; |
return; |
| |
} else if (Enabled(&auth->conf.options, AUTH_CONF_RADIUS_AUTH)) { |
| |
auth->params.authentic = AUTH_CONF_RADIUS_AUTH; |
| |
Log(LG_AUTH, ("[%s] AUTH: Trying RADIUS", auth->info.lnkname)); |
| |
if (RadiusAuthenticate(auth)) { |
| |
Log(LG_ERR | LG_AUTH, ("[%s] AUTH: RADIUS returned error", |
| |
auth->info.lnkname)); |
| |
} else { |
| |
Log(LG_AUTH, ("[%s] AUTH: RADIUS returned: %s", |
| |
auth->info.lnkname, AuthStatusText(auth->status))); |
| |
if (auth->status == AUTH_STATUS_SUCCESS) |
| |
return; |
| |
} |
| } |
} |
| } |
|
| |
|
| if (auth->proto == PROTO_EAP && auth->eap_radius) { |
|
| auth->params.authentic = AUTH_CONF_RADIUS_AUTH; |
|
| RadiusEapProxy(auth); |
|
| return; |
|
| } else if (Enabled(&auth->conf.options, AUTH_CONF_RADIUS_AUTH)) { |
|
| auth->params.authentic = AUTH_CONF_RADIUS_AUTH; |
|
| Log(LG_AUTH, ("[%s] AUTH: Trying RADIUS", auth->info.lnkname)); |
|
| if (RadiusAuthenticate(auth)) { |
|
| Log(LG_AUTH, ("[%s] AUTH: RADIUS returned error", |
|
| auth->info.lnkname)); |
|
| } else { |
|
| Log(LG_AUTH, ("[%s] AUTH: RADIUS returned: %s", |
|
| auth->info.lnkname, AuthStatusText(auth->status))); |
|
| if (auth->status == AUTH_STATUS_SUCCESS) |
|
| return; |
|
| } |
|
| } |
|
| |
|
| #ifdef USE_PAM |
#ifdef USE_PAM |
| if (Enabled(&auth->conf.options, AUTH_CONF_PAM_AUTH)) { | if (Enabled(&auth->conf.options, AUTH_CONF_PAM_AUTH)) { |
| auth->params.authentic = AUTH_CONF_PAM_AUTH; | auth->params.authentic = AUTH_CONF_PAM_AUTH; |
| Log(LG_AUTH, ("[%s] AUTH: Trying PAM", auth->info.lnkname)); | Log(LG_AUTH, ("[%s] AUTH: Trying PAM", auth->info.lnkname)); |
| AuthPAM(auth); | AuthPAM(auth); |
| Log(LG_AUTH, ("[%s] AUTH: PAM returned: %s", | Log(LG_AUTH, ("[%s] AUTH: PAM returned: %s", |
| auth->info.lnkname, AuthStatusText(auth->status))); | auth->info.lnkname, AuthStatusText(auth->status))); |
| if (auth->status == AUTH_STATUS_SUCCESS | if (auth->status == AUTH_STATUS_SUCCESS |
| || auth->status == AUTH_STATUS_UNDEF) | || auth->status == AUTH_STATUS_UNDEF) |
| return; | return; |
| } | } |
| #endif |
#endif |
| |
|
| #ifdef USE_SYSTEM |
#ifdef USE_SYSTEM |
| if (Enabled(&auth->conf.options, AUTH_CONF_SYSTEM_AUTH)) { | if (Enabled(&auth->conf.options, AUTH_CONF_SYSTEM_AUTH)) { |
| auth->params.authentic = AUTH_CONF_SYSTEM_AUTH; | auth->params.authentic = AUTH_CONF_SYSTEM_AUTH; |
| Log(LG_AUTH, ("[%s] AUTH: Trying SYSTEM", auth->info.lnkname)); | Log(LG_AUTH, ("[%s] AUTH: Trying SYSTEM", auth->info.lnkname)); |
| AuthSystem(auth); | AuthSystem(auth); |
| Log(LG_AUTH, ("[%s] AUTH: SYSTEM returned: %s", | Log(LG_AUTH, ("[%s] AUTH: SYSTEM returned: %s", |
| auth->info.lnkname, AuthStatusText(auth->status))); | auth->info.lnkname, AuthStatusText(auth->status))); |
| if (auth->status == AUTH_STATUS_SUCCESS | if (auth->status == AUTH_STATUS_SUCCESS |
| || auth->status == AUTH_STATUS_UNDEF) | || auth->status == AUTH_STATUS_UNDEF) |
| return; | return; |
| } | } |
| #endif |
#endif |
| | |
| #ifdef USE_OPIE |
#ifdef USE_OPIE |
| if (Enabled(&auth->conf.options, AUTH_CONF_OPIE)) { | if (Enabled(&auth->conf.options, AUTH_CONF_OPIE)) { |
| auth->params.authentic = AUTH_CONF_OPIE; | auth->params.authentic = AUTH_CONF_OPIE; |
| Log(LG_AUTH, ("[%s] AUTH: Trying OPIE", auth->info.lnkname)); | Log(LG_AUTH, ("[%s] AUTH: Trying OPIE", auth->info.lnkname)); |
| AuthOpie(auth); | AuthOpie(auth); |
| Log(LG_AUTH, ("[%s] AUTH: OPIE returned: %s", | Log(LG_AUTH, ("[%s] AUTH: OPIE returned: %s", |
| auth->info.lnkname, AuthStatusText(auth->status))); | auth->info.lnkname, AuthStatusText(auth->status))); |
| if (auth->status == AUTH_STATUS_SUCCESS | if (auth->status == AUTH_STATUS_SUCCESS |
| || auth->status == AUTH_STATUS_UNDEF) | || auth->status == AUTH_STATUS_UNDEF) |
| return; | return; |
| } | } |
| #endif /* USE_OPIE */ | #endif /* USE_OPIE */ |
| | |
| if (Enabled(&auth->conf.options, AUTH_CONF_INTERNAL)) { | |
| auth->params.authentic = AUTH_CONF_INTERNAL; | |
| Log(LG_AUTH, ("[%s] AUTH: Trying INTERNAL", auth->info.lnkname)); | |
| AuthInternal(auth); | |
| Log(LG_AUTH, ("[%s] AUTH: INTERNAL returned: %s", | |
| auth->info.lnkname, AuthStatusText(auth->status))); | |
| if (auth->status == AUTH_STATUS_SUCCESS | |
| || auth->status == AUTH_STATUS_UNDEF) | |
| return; | |
| } | |
| |
|
| Log(LG_AUTH, ("[%s] AUTH: ran out of backends", auth->info.lnkname)); | if (Enabled(&auth->conf.options, AUTH_CONF_INTERNAL)) { |
| auth->status = AUTH_STATUS_FAIL; | auth->params.authentic = AUTH_CONF_INTERNAL; |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | Log(LG_AUTH, ("[%s] AUTH: Trying INTERNAL", auth->info.lnkname)); |
| | AuthInternal(auth); |
| | Log(LG_AUTH, ("[%s] AUTH: INTERNAL returned: %s", |
| | auth->info.lnkname, AuthStatusText(auth->status))); |
| | if (auth->status == AUTH_STATUS_SUCCESS |
| | || auth->status == AUTH_STATUS_UNDEF) |
| | return; |
| | } |
| | Log(LG_AUTH, ("[%s] AUTH: ran out of backends", auth->info.lnkname)); |
| | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| } |
} |
| |
|
| /* |
/* |
| * AuthAsyncFinish() |
* AuthAsyncFinish() |
| * | * |
| * Return point for the auth thread |
* Return point for the auth thread |
| */ |
*/ |
| | |
| static void |
static void |
| AuthAsyncFinish(void *arg, int was_canceled) |
AuthAsyncFinish(void *arg, int was_canceled) |
| { |
{ |
| AuthData auth = (AuthData)arg; | AuthData auth = (AuthData) arg; |
| Link l; | Link l; |
| |
|
| if (was_canceled) | if (was_canceled) |
| Log(LG_AUTH2, ("[%s] AUTH: Thread was canceled", auth->info.lnkname)); | Log(LG_AUTH2, ("[%s] AUTH: Thread was canceled", auth->info.lnkname)); |
| |
|
| /* cleanup */ | /* cleanup */ |
| RadiusClose(auth); | RadiusClose(auth); |
| | |
| if (was_canceled) { | |
| AuthDataDestroy(auth); | |
| return; | |
| } | |
| | |
| l = gLinks[auth->info.linkID]; | |
| if (l == NULL) { | |
| AuthDataDestroy(auth); | |
| return; | |
| } | |
| |
|
| Log(LG_AUTH2, ("[%s] AUTH: Thread finished normally", l->name)); | if (was_canceled) { |
| | AuthDataDestroy(auth); |
| | return; |
| | } |
| | l = gLinks[auth->info.linkID]; |
| | if (l == NULL) { |
| | AuthDataDestroy(auth); |
| | return; |
| | } |
| | Log(LG_AUTH2, ("[%s] AUTH: Thread finished normally", l->name)); |
| |
|
| /* Replace modified data */ | /* Replace modified data */ |
| authparamsDestroy(&l->lcp.auth.params); | authparamsDestroy(&l->lcp.auth.params); |
| authparamsMove(&auth->params,&l->lcp.auth.params); | authparamsMove(&auth->params, &l->lcp.auth.params); |
| |
|
| if (strcmp(l->lcp.auth.params.action, "drop") == 0) { | if (strcmp(l->lcp.auth.params.action, "drop") == 0) { |
| auth->status = AUTH_STATUS_FAIL; | auth->status = AUTH_STATUS_FAIL; |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| } else if (strncmp(l->lcp.auth.params.action, "forward ", 8) == 0) { | } else if (strncmp(l->lcp.auth.params.action, "forward ", 8) == 0) { |
| const char *rept = l->lcp.auth.params.action + 8; | const char *rept = l->lcp.auth.params.action + 8; |
| |
|
| /* Action told we must forward this connection */ | /* Action told we must forward this connection */ |
| if (RepCreate(l, rept)) { | if (RepCreate(l, rept)) { |
| Log(LG_ERR, ("[%s] Repeater to \"%s\" creation error", l->name, rept)); | Log(LG_ERR, ("[%s] Repeater to \"%s\" creation error", l->name, rept)); |
| PhysClose(l); | PhysClose(l); |
| AuthDataDestroy(auth); | AuthDataDestroy(auth); |
| return; | return; |
| | } |
| | /* Create repeater */ |
| | RepIncoming(l); |
| | /* Reconnect link netgraph hook to repeater */ |
| | LinkNgToRep(l); |
| | /* Kill the LCP */ |
| | LcpDown(l); |
| | LcpClose(l); |
| | AuthDataDestroy(auth); |
| | return; |
| } |
} |
| /* Create repeater */ | auth->finish(l, auth); |
| RepIncoming(l); | |
| /* Reconnect link netgraph hook to repeater */ | |
| LinkNgToRep(l); | |
| /* Kill the LCP */ | |
| LcpDown(l); | |
| LcpClose(l); | |
| AuthDataDestroy(auth); | |
| return; | |
| } | |
| |
| auth->finish(l, auth); | |
| } |
} |
| |
|
| /* |
/* |
| * AuthInternal() |
* AuthInternal() |
| * | * |
| * Authenticate against mpd.secret |
* Authenticate against mpd.secret |
| */ |
*/ |
| | |
| static void |
static void |
| AuthInternal(AuthData auth) |
AuthInternal(AuthData auth) |
| { |
{ |
| if (AuthGetData(auth->params.authname, auth->params.password, | if (AuthGetData(auth->params.authname, auth->params.password, |
| sizeof(auth->params.password), &auth->params.range, | sizeof(auth->params.password), &auth->params.range, |
| &auth->params.range_valid) < 0) { |
&auth->params.range_valid) < 0) { |
| Log(LG_AUTH, ("[%s] AUTH: User \"%s\" not found in secret file", | Log(LG_AUTH, ("[%s] AUTH: User \"%s\" not found in secret file", |
| auth->info.lnkname, auth->params.authname)); | auth->info.lnkname, auth->params.authname)); |
| auth->status = AUTH_STATUS_FAIL; | auth->status = AUTH_STATUS_FAIL; |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| return; | return; |
| } | } |
| auth->status = AUTH_STATUS_UNDEF; | auth->status = AUTH_STATUS_UNDEF; |
| } |
} |
| |
|
| #ifdef USE_SYSTEM |
#ifdef USE_SYSTEM |
| /* |
/* |
| * AuthSystem() |
* AuthSystem() |
| * | * |
| * Authenticate against Systems password database |
* Authenticate against Systems password database |
| */ |
*/ |
| | |
| static void |
static void |
| AuthSystem(AuthData auth) |
AuthSystem(AuthData auth) |
| { |
{ |
| PapParams pp = &auth->params.pap; | PapParams pp = &auth->params.pap; |
| struct passwd *pw; | struct passwd *pw; |
| struct passwd pwc; | struct passwd pwc; |
| u_char *bin; | u_char *bin; |
| int err; | int err; |
| | |
| /* protect getpwnam and errno | |
| * NOTE: getpwnam_r doesen't exists on FreeBSD < 5.1 */ | |
| GIANT_MUTEX_LOCK(); | |
| errno = 0; | |
| pw = getpwnam(auth->params.authname); | |
| if (!pw) { | |
| err=errno; | |
| GIANT_MUTEX_UNLOCK(); /* We must release lock before Log() */ | |
| if (err) | |
| Log(LG_ERR, ("[%s] AUTH: Error retrieving passwd: %s", | |
| auth->info.lnkname, strerror(err))); | |
| else | |
| Log(LG_AUTH, ("[%s] AUTH: User \"%s\" not found in the systems database", | |
| auth->info.lnkname, auth->params.authname)); | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | |
| return; | |
| } | |
| memcpy(&pwc,pw,sizeof(struct passwd)); /* we must make copy before release lock */ | |
| GIANT_MUTEX_UNLOCK(); | |
| | |
| Log(LG_AUTH, ("[%s] AUTH: Found user %s Uid:%d Gid:%d Fmt:%*.*s", | |
| auth->info.lnkname, pwc.pw_name, pwc.pw_uid, pwc.pw_gid, 3, 3, pwc.pw_passwd)); | |
| |
|
| if (auth->proto == PROTO_PAP) { | /* |
| /* protect non-ts crypt() */ | * protect getpwnam and errno NOTE: getpwnam_r doesen't exists on |
| GIANT_MUTEX_LOCK(); | * FreeBSD < 5.1 |
| if (strcmp(crypt(pp->peer_pass, pwc.pw_passwd), pwc.pw_passwd) == 0) { | */ |
| auth->status = AUTH_STATUS_SUCCESS; | GIANT_MUTEX_LOCK(); |
| } else { | errno = 0; |
| auth->status = AUTH_STATUS_FAIL; | pw = getpwnam(auth->params.authname); |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | if (!pw) { |
| } | err = errno; |
| GIANT_MUTEX_UNLOCK(); | GIANT_MUTEX_UNLOCK(); /* We must release lock before Log() */ |
| return; | if (err) |
| } else if (auth->proto == PROTO_CHAP | Perror("[%s] AUTH: Error retrieving passwd", auth->info.lnkname); |
| && (auth->alg == CHAP_ALG_MSOFT | else |
| || auth->alg == CHAP_ALG_MSOFTv2)) { | Log(LG_AUTH, ("[%s] AUTH: User \"%s\" not found in the systems database", |
| | auth->info.lnkname, auth->params.authname)); |
| | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| | return; |
| | } |
| | memcpy(&pwc, pw, sizeof(struct passwd)); /* we must make copy |
| | * before release lock */ |
| | GIANT_MUTEX_UNLOCK(); |
| |
|
| if (!strstr(pwc.pw_passwd, "$3$$")) { | Log(LG_AUTH, ("[%s] AUTH: Found user %s Uid:%d Gid:%d Fmt:%*.*s", |
| Log(LG_AUTH, ("[%s] AUTH: Password has the wrong format, nth ($3$) is needed", | auth->info.lnkname, pwc.pw_name, pwc.pw_uid, pwc.pw_gid, 3, 3, pwc.pw_passwd)); |
| auth->info.lnkname)); | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | |
| return; | |
| } | |
| |
|
| bin = Hex2Bin(&pwc.pw_passwd[4]); | if (auth->proto == PROTO_PAP) { |
| memcpy(auth->params.msoft.nt_hash, bin, sizeof(auth->params.msoft.nt_hash)); | /* protect non-ts crypt() */ |
| Freee(bin); | GIANT_MUTEX_LOCK(); |
| NTPasswordHashHash(auth->params.msoft.nt_hash, auth->params.msoft.nt_hash_hash); | if (strcmp(crypt(pp->peer_pass, pwc.pw_passwd), pwc.pw_passwd) == 0) { |
| auth->params.msoft.has_nt_hash = TRUE; | auth->status = AUTH_STATUS_SUCCESS; |
| auth->status = AUTH_STATUS_UNDEF; | } else { |
| return; | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| | } |
| | GIANT_MUTEX_UNLOCK(); |
| | return; |
| | } else if (auth->proto == PROTO_CHAP |
| | && (auth->alg == CHAP_ALG_MSOFT |
| | || auth->alg == CHAP_ALG_MSOFTv2)) { |
| |
|
| } else { | if (!strstr(pwc.pw_passwd, "$3$$")) { |
| Log(LG_ERR, ("[%s] AUTH: Using systems password database only possible for PAP and MS-CHAP", | Log(LG_AUTH, ("[%s] AUTH: Password has the wrong format, nth ($3$) is needed", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| auth->status = AUTH_STATUS_FAIL; | auth->status = AUTH_STATUS_FAIL; |
| auth->why_fail = AUTH_FAIL_NOT_EXPECTED; | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| return; | return; |
| } | } |
| | bin = Hex2Bin(&pwc.pw_passwd[4]); |
| | memcpy(auth->params.msoft.nt_hash, bin, sizeof(auth->params.msoft.nt_hash)); |
| | Freee(bin); |
| | NTPasswordHashHash(auth->params.msoft.nt_hash, auth->params.msoft.nt_hash_hash); |
| | auth->params.msoft.has_nt_hash = TRUE; |
| | auth->status = AUTH_STATUS_UNDEF; |
| | return; |
| |
|
| |
} else { |
| |
Log(LG_ERR, ("[%s] AUTH: Using systems password database only possible for PAP and MS-CHAP", |
| |
auth->info.lnkname)); |
| |
auth->status = AUTH_STATUS_FAIL; |
| |
auth->why_fail = AUTH_FAIL_NOT_EXPECTED; |
| |
return; |
| |
} |
| |
|
| } |
} |
| |
|
| /* |
/* |
| * AuthSystemAcct() |
* AuthSystemAcct() |
| * | * |
| * Account with system |
* Account with system |
| */ |
*/ |
| |
|
|
Line 1410 AuthSystem(AuthData auth)
|
Line 1431 AuthSystem(AuthData auth)
|
| static int |
static int |
| AuthSystemAcct(AuthData auth) |
AuthSystemAcct(AuthData auth) |
| { |
{ |
| struct utmpx ut; | struct utmpx ut; |
| |
|
| memset(&ut, 0, sizeof(ut)); |
memset(&ut, 0, sizeof(ut)); |
| snprintf(ut.ut_id, sizeof(ut.ut_id), "mpd%x", auth->info.linkID); |
snprintf(ut.ut_id, sizeof(ut.ut_id), "mpd%x", auth->info.linkID); |
|
Line 1422 AuthSystemAcct(AuthData auth)
|
Line 1443 AuthSystemAcct(AuthData auth)
|
| strlcpy(ut.ut_user, auth->params.authname, sizeof(ut.ut_user)); |
strlcpy(ut.ut_user, auth->params.authname, sizeof(ut.ut_user)); |
| gettimeofday(&ut.ut_tv, NULL); |
gettimeofday(&ut.ut_tv, NULL); |
| Log(LG_AUTH, ("[%s] ACCT: wtmp %s %s %s login", auth->info.lnkname, ut.ut_line, |
Log(LG_AUTH, ("[%s] ACCT: wtmp %s %s %s login", auth->info.lnkname, ut.ut_line, |
| ut.ut_user, ut.ut_host)); | ut.ut_user, ut.ut_host)); |
| pututxline(&ut); |
pututxline(&ut); |
| } else if (auth->acct_type == AUTH_ACCT_STOP) { |
} else if (auth->acct_type == AUTH_ACCT_STOP) { |
| ut.ut_type = DEAD_PROCESS; |
ut.ut_type = DEAD_PROCESS; |
|
Line 1431 AuthSystemAcct(AuthData auth)
|
Line 1452 AuthSystemAcct(AuthData auth)
|
| } |
} |
| return (0); |
return (0); |
| } |
} |
| |
|
| #else |
#else |
| static int |
static int |
| AuthSystemAcct(AuthData auth) |
AuthSystemAcct(AuthData auth) |
| { |
{ |
| struct utmp ut; | struct utmp ut; |
| |
|
| memset(&ut, 0, sizeof(ut)); |
memset(&ut, 0, sizeof(ut)); |
| strlcpy(ut.ut_line, auth->info.lnkname, sizeof(ut.ut_line)); |
strlcpy(ut.ut_line, auth->info.lnkname, sizeof(ut.ut_line)); |
| |
|
| if (auth->acct_type == AUTH_ACCT_START) { |
if (auth->acct_type == AUTH_ACCT_START) { |
| time_t t; | time_t t; |
| |
|
| strlcpy(ut.ut_host, auth->params.peeraddr, sizeof(ut.ut_host)); | strlcpy(ut.ut_host, auth->params.peeraddr, sizeof(ut.ut_host)); |
| strlcpy(ut.ut_name, auth->params.authname, sizeof(ut.ut_name)); | strlcpy(ut.ut_name, auth->params.authname, sizeof(ut.ut_name)); |
| time(&t); | time(&t); |
| ut.ut_time = t; | ut.ut_time = t; |
| login(&ut); | login(&ut); |
| Log(LG_AUTH, ("[%s] ACCT: wtmp %s %s %s login", auth->info.lnkname, ut.ut_line, | Log(LG_AUTH, ("[%s] ACCT: wtmp %s %s %s login", auth->info.lnkname, ut.ut_line, |
| ut.ut_name, ut.ut_host)); | ut.ut_name, ut.ut_host)); |
| } else if (auth->acct_type == AUTH_ACCT_STOP) { |
} else if (auth->acct_type == AUTH_ACCT_STOP) { |
| Log(LG_AUTH, ("[%s] ACCT: wtmp %s logout", auth->info.lnkname, ut.ut_line)); | Log(LG_AUTH, ("[%s] ACCT: wtmp %s logout", auth->info.lnkname, ut.ut_line)); |
| logout(ut.ut_line); | logout(ut.ut_line); |
| logwtmp(ut.ut_line, "", ""); | logwtmp(ut.ut_line, "", ""); |
| } |
} |
| return (0); |
return (0); |
| } |
} |
| #endif /* __FreeBSD_version >= 900007 */ |
|
| #endif /* USE_SYSTEM */ |
|
| |
|
| |
#endif /* __FreeBSD_version >= 900007 */ |
| |
#endif /* USE_SYSTEM */ |
| |
|
| #ifdef USE_PAM |
#ifdef USE_PAM |
| /* |
/* |
| * AuthPAM() |
* AuthPAM() |
| * | * |
| * Authenticate with PAM system |
* Authenticate with PAM system |
| */ |
*/ |
| |
|
| static int |
static int |
| pam_conv(int n, const struct pam_message **msg, struct pam_response **resp, |
pam_conv(int n, const struct pam_message **msg, struct pam_response **resp, |
| void *data) | void *data) |
| { |
{ |
| AuthData auth = (AuthData)data; | AuthData auth = (AuthData) data; |
| int i; | int i; |
| |
|
| for (i = 0; i < n; i++) { | for (i = 0; i < n; i++) { |
| Log(LG_AUTH2, ("[%s] AUTH: PAM: %s", | Log(LG_AUTH2, ("[%s] AUTH: PAM: %s", |
| auth->info.lnkname, msg[i]->msg)); | auth->info.lnkname, msg[i]->msg)); |
| } | } |
| |
|
| /* We support only requests for password */ | /* We support only requests for password */ |
| if (n != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) | if (n != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) |
| return (PAM_CONV_ERR); | return (PAM_CONV_ERR); |
| |
|
| if ((*resp = malloc(sizeof(struct pam_response))) == NULL) | if ((*resp = malloc(sizeof(struct pam_response))) == NULL) |
| return (PAM_CONV_ERR); | return (PAM_CONV_ERR); |
| (*resp)[0].resp = strdup(auth->params.pap.peer_pass); | (*resp)[0].resp = strdup(auth->params.pap.peer_pass); |
| (*resp)[0].resp_retcode = 0; | (*resp)[0].resp_retcode = 0; |
| |
|
| return ((*resp)[0].resp != NULL ? PAM_SUCCESS : PAM_CONV_ERR); | return ((*resp)[0].resp != NULL ? PAM_SUCCESS : PAM_CONV_ERR); |
| } |
} |
| | |
| static void |
static void |
| AuthPAM(AuthData auth) |
AuthPAM(AuthData auth) |
| { |
{ |
| struct pam_conv pamc = { | struct pam_conv pamc = { |
| &pam_conv, | &pam_conv, |
| auth | auth |
| }; | }; |
| pam_handle_t *pamh; | pam_handle_t *pamh; |
| int status; | int status; |
| |
|
| if (auth->proto != PROTO_PAP) { | if (auth->proto != PROTO_PAP) { |
| Log(LG_ERR, ("[%s] AUTH: Using PAM only possible for PAP", auth->info.lnkname)); | Log(LG_ERR, ("[%s] AUTH: Using PAM only possible for PAP", auth->info.lnkname)); |
| auth->status = AUTH_STATUS_FAIL; | auth->status = AUTH_STATUS_FAIL; |
| auth->why_fail = AUTH_FAIL_NOT_EXPECTED; | auth->why_fail = AUTH_FAIL_NOT_EXPECTED; |
| return; | return; |
| } | } |
| | if (pam_start(gPamService, auth->params.authname, &pamc, &pamh) != PAM_SUCCESS) { |
| if (pam_start(gPamService, auth->params.authname, &pamc, &pamh) != PAM_SUCCESS) { | Log(LG_ERR, ("[%s] AUTH: PAM error", auth->info.lnkname)); |
| Log(LG_ERR, ("[%s] AUTH: PAM error", auth->info.lnkname)); | auth->status = AUTH_STATUS_FAIL; |
| auth->status = AUTH_STATUS_FAIL; | auth->why_fail = AUTH_FAIL_NOT_EXPECTED; |
| auth->why_fail = AUTH_FAIL_NOT_EXPECTED; | return; |
| return; | } |
| } | if (auth->params.peeraddr[0] && |
| | pam_set_item(pamh, PAM_RHOST, auth->params.peeraddr) != PAM_SUCCESS) { |
| | Log(LG_ERR, ("[%s] AUTH: PAM set PAM_RHOST error", auth->info.lnkname)); |
| | } |
| | if (pam_set_item(pamh, PAM_TTY, auth->info.lnkname) != PAM_SUCCESS) { |
| | Log(LG_ERR, ("[%s] AUTH: PAM set PAM_TTY error", auth->info.lnkname)); |
| | } |
| | status = pam_authenticate(pamh, 0); |
| |
|
| if (auth->params.peeraddr[0] && | if (status == PAM_SUCCESS) { |
| pam_set_item(pamh, PAM_RHOST, auth->params.peeraddr) != PAM_SUCCESS) { | status = pam_acct_mgmt(pamh, 0); |
| Log(LG_ERR, ("[%s] AUTH: PAM set PAM_RHOST error", auth->info.lnkname)); | |
| } | |
| |
| if (pam_set_item(pamh, PAM_TTY, auth->info.lnkname) != PAM_SUCCESS) { | |
| Log(LG_ERR, ("[%s] AUTH: PAM set PAM_TTY error", auth->info.lnkname)); | |
| } | |
| |
| status = pam_authenticate(pamh, 0); | |
| |
| if (status == PAM_SUCCESS) { | |
| status = pam_acct_mgmt(pamh, 0); | |
| } | |
| |
| if (status == PAM_SUCCESS) { | |
| auth->status = AUTH_STATUS_SUCCESS; | |
| } else { | |
| Log(LG_AUTH, ("[%s] AUTH: PAM error: %s", | |
| auth->info.lnkname, pam_strerror(pamh, status))); | |
| switch (status) { | |
| case PAM_AUTH_ERR: | |
| case PAM_USER_UNKNOWN: | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | |
| break; | |
| case PAM_ACCT_EXPIRED: | |
| case PAM_AUTHTOK_EXPIRED: | |
| case PAM_CRED_EXPIRED: | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_ACCT_DISABLED; | |
| break; | |
| default: | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_NOT_EXPECTED; | |
| } |
} |
| } | if (status == PAM_SUCCESS) { |
| | auth->status = AUTH_STATUS_SUCCESS; |
| | } else { |
| | Log(LG_AUTH, ("[%s] AUTH: PAM error: %s", |
| | auth->info.lnkname, pam_strerror(pamh, status))); |
| | switch (status) { |
| | case PAM_AUTH_ERR: |
| | case PAM_USER_UNKNOWN: |
| | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| | break; |
| | case PAM_ACCT_EXPIRED: |
| | case PAM_AUTHTOK_EXPIRED: |
| | case PAM_CRED_EXPIRED: |
| | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_ACCT_DISABLED; |
| | break; |
| | default: |
| | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_NOT_EXPECTED; |
| | } |
| | } |
| |
|
| pam_end(pamh, status); | pam_end(pamh, status); |
| } |
} |
| |
|
| /* |
/* |
| * AuthPAMAcct() |
* AuthPAMAcct() |
| * | * |
| * Account with system |
* Account with system |
| */ |
*/ |
| |
|
| static int |
static int |
| AuthPAMAcct(AuthData auth) |
AuthPAMAcct(AuthData auth) |
| { |
{ |
| pam_handle_t *pamh; | pam_handle_t *pamh; |
| int status; | int status; |
| struct pam_conv pamc = { | struct pam_conv pamc = { |
| &pam_conv, | &pam_conv, |
| auth | auth |
| }; | }; |
| | |
| if (auth->acct_type != AUTH_ACCT_START && | |
| auth->acct_type != AUTH_ACCT_STOP) { | |
| return (0); | |
| } | |
| |
|
| if (pam_start(gPamService, auth->params.authname, &pamc, &pamh) != PAM_SUCCESS) { | if (auth->acct_type != AUTH_ACCT_START && |
| Log(LG_ERR, ("[%s] ACCT: PAM error", auth->info.lnkname)); | auth->acct_type != AUTH_ACCT_STOP) { |
| return (-1); | return (0); |
| } | } |
| if (pam_start(gPamService, auth->params.authname, &pamc, &pamh) != PAM_SUCCESS) { |
| if (auth->params.peeraddr[0] && | Log(LG_ERR, ("[%s] ACCT: PAM error", auth->info.lnkname)); |
| pam_set_item(pamh, PAM_RHOST, auth->params.peeraddr) != PAM_SUCCESS) { | return (-1); |
| Log(LG_ERR, ("[%s] ACCT: PAM set PAM_RHOST error", auth->info.lnkname)); | } |
| return (-1); | if (auth->params.peeraddr[0] && |
| } | pam_set_item(pamh, PAM_RHOST, auth->params.peeraddr) != PAM_SUCCESS) { |
| Log(LG_ERR, ("[%s] ACCT: PAM set PAM_RHOST error", auth->info.lnkname)); |
| if (pam_set_item(pamh, PAM_TTY, auth->info.lnkname) != PAM_SUCCESS) { | return (-1); |
| Log(LG_ERR, ("[%s] ACCT: PAM set PAM_TTY error", auth->info.lnkname)); | } |
| return (-1); | if (pam_set_item(pamh, PAM_TTY, auth->info.lnkname) != PAM_SUCCESS) { |
| } | Log(LG_ERR, ("[%s] ACCT: PAM set PAM_TTY error", auth->info.lnkname)); |
| return (-1); |
| if (auth->acct_type == AUTH_ACCT_START) { | } |
| Log(LG_AUTH, ("[%s] ACCT: PAM open session \"%s\"", | if (auth->acct_type == AUTH_ACCT_START) { |
| auth->info.lnkname, auth->params.authname)); | Log(LG_AUTH, ("[%s] ACCT: PAM open session \"%s\"", |
| status = pam_open_session(pamh, 0); | auth->info.lnkname, auth->params.authname)); |
| } else { | status = pam_open_session(pamh, 0); |
| Log(LG_AUTH, ("[%s] ACCT: PAM close session \"%s\"", | } else { |
| auth->info.lnkname, auth->params.authname)); | Log(LG_AUTH, ("[%s] ACCT: PAM close session \"%s\"", |
| status = pam_close_session(pamh, 0); | auth->info.lnkname, auth->params.authname)); |
| } | status = pam_close_session(pamh, 0); |
| if (status != PAM_SUCCESS) { | } |
| Log(LG_AUTH, ("[%s] ACCT: PAM session error", | if (status != PAM_SUCCESS) { |
| auth->info.lnkname)); | Log(LG_AUTH, ("[%s] ACCT: PAM session error", |
| return (-1); | auth->info.lnkname)); |
| } | return (-1); |
| | } |
| pam_end(pamh, status); | pam_end(pamh, status); |
| return (0); | return (0); |
| } |
} |
| #endif /* USE_PAM */ |
|
| |
|
| |
#endif /* USE_PAM */ |
| |
|
| #ifdef USE_OPIE |
#ifdef USE_OPIE |
| /* |
/* |
| * AuthOpie() |
* AuthOpie() |
|
Line 1621 AuthPAMAcct(AuthData auth)
|
Line 1635 AuthPAMAcct(AuthData auth)
|
| static void |
static void |
| AuthOpie(AuthData auth) |
AuthOpie(AuthData auth) |
| { |
{ |
| PapParams const pp = &auth->params.pap; | PapParams const pp = &auth->params.pap; |
| struct opie_otpkey key; | struct opie_otpkey key; |
| char opieprompt[OPIE_CHALLENGE_MAX + 1]; | char opieprompt[OPIE_CHALLENGE_MAX + 1]; |
| int ret, n; | int ret, n; |
| char secret[OPIE_SECRET_MAX + 1]; | char secret[OPIE_SECRET_MAX + 1]; |
| char english[OPIE_RESPONSE_MAX + 1]; | char english[OPIE_RESPONSE_MAX + 1]; |
| |
|
| ret = opiechallenge(&auth->opie.data, auth->params.authname, opieprompt); | ret = opiechallenge(&auth->opie.data, auth->params.authname, opieprompt); |
| |
|
| auth->status = AUTH_STATUS_UNDEF; | auth->status = AUTH_STATUS_UNDEF; |
| | |
| switch (ret) { | |
| case 0: | |
| break; | |
| | |
| case 1: | |
| Log(LG_ERR, ("[%s] AUTH: User \"%s\" not found in opiekeys", | |
| auth->info.lnkname, auth->params.authname)); | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | |
| return; | |
| |
|
| case -1: | switch (ret) { |
| case 2: | case 0: |
| default: | break; |
| Log(LG_ERR, ("[%s] AUTH: System error", auth->info.lnkname)); | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_NOT_EXPECTED; | |
| return; | |
| }; | |
| |
|
| Log(LG_AUTH, ("[%s] AUTH: Opieprompt:%s", auth->info.lnkname, opieprompt)); | case 1: |
| | Log(LG_ERR, ("[%s] AUTH: User \"%s\" not found in opiekeys", |
| | auth->info.lnkname, auth->params.authname)); |
| | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| | return; |
| |
|
| if (auth->proto == PROTO_PAP ) { | case -1: |
| if (!opieverify(&auth->opie.data, pp->peer_pass)) { | case 2: |
| auth->status = AUTH_STATUS_SUCCESS; | default: |
| } else { | Log(LG_ERR, ("[%s] AUTH: System error", auth->info.lnkname)); |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | auth->status = AUTH_STATUS_FAIL; |
| auth->status = AUTH_STATUS_FAIL; | auth->why_fail = AUTH_FAIL_NOT_EXPECTED; |
| } | return; |
| return; | }; |
| } | |
| |
|
| if (AuthGetData(auth->params.authname, secret, sizeof(secret), NULL, NULL) < 0) { | Log(LG_AUTH, ("[%s] AUTH: Opieprompt:%s", auth->info.lnkname, opieprompt)); |
| Log(LG_AUTH, ("[%s] AUTH: Can't get credentials for \"%s\"", | |
| auth->info.lnkname, auth->params.authname)); | |
| auth->status = AUTH_STATUS_FAIL; | |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | |
| return; | |
| } | |
| | |
| opiekeycrunch(OPIE_ALG_MD5, &key, auth->opie.data.opie_seed, secret); | |
| n = auth->opie.data.opie_n - 1; | |
| while (n-- > 0) | |
| opiehash(&key, OPIE_ALG_MD5); | |
| |
|
| opiebtoe(english, &key); | if (auth->proto == PROTO_PAP) { |
| strlcpy(auth->params.password, english, sizeof(auth->params.password)); | if (!opieverify(&auth->opie.data, pp->peer_pass)) { |
| | auth->status = AUTH_STATUS_SUCCESS; |
| | } else { |
| | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| | auth->status = AUTH_STATUS_FAIL; |
| | } |
| | return; |
| | } |
| | if (AuthGetData(auth->params.authname, secret, sizeof(secret), NULL, NULL) < 0) { |
| | Log(LG_AUTH, ("[%s] AUTH: Can't get credentials for \"%s\"", |
| | auth->info.lnkname, auth->params.authname)); |
| | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| | return; |
| | } |
| | opiekeycrunch(OPIE_ALG_MD5, &key, auth->opie.data.opie_seed, secret); |
| | n = auth->opie.data.opie_n - 1; |
| | while (n-- > 0) |
| | opiehash(&key, OPIE_ALG_MD5); |
| | |
| | opiebtoe(english, &key); |
| | strlcpy(auth->params.password, english, sizeof(auth->params.password)); |
| } |
} |
| #endif /* USE_OPIE */ |
|
| |
|
| |
#endif /* USE_OPIE */ |
| |
|
| /* |
/* |
| * AuthPreChecks() |
* AuthPreChecks() |
| */ |
*/ |
|
Line 1690 static int
|
Line 1703 static int
|
| AuthPreChecks(AuthData auth) |
AuthPreChecks(AuthData auth) |
| { |
{ |
| |
|
| if (!strlen(auth->params.authname)) { | if (!strlen(auth->params.authname)) { |
| Log(LG_AUTH, ("[%s] AUTH: We don't accept empty usernames", auth->info.lnkname)); | Log(LG_AUTH, ("[%s] AUTH: We don't accept empty usernames", auth->info.lnkname)); |
| auth->status = AUTH_STATUS_FAIL; | auth->status = AUTH_STATUS_FAIL; |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| return (-1); | return (-1); |
| } | |
| /* check max. number of logins */ | |
| if (gMaxLogins != 0) { | |
| int ac; | |
| u_long num = 0; | |
| for(ac = 0; ac < gNumBundles; ac++) { | |
| if (gBundles[ac] && gBundles[ac]->open) { | |
| if (gMaxLoginsCI) { | |
| if (!strcasecmp(gBundles[ac]->params.authname, auth->params.authname)) | |
| num++; | |
| } else { | |
| if (!strcmp(gBundles[ac]->params.authname, auth->params.authname)) | |
| num++; | |
| } |
} |
| } | /* check max. number of logins */ |
| } | if (gMaxLogins != 0) { |
| | int ac; |
| | u_long num = 0; |
| |
|
| if (num >= gMaxLogins) { | for (ac = 0; ac < gNumBundles; ac++) { |
| Log(LG_AUTH, ("[%s] AUTH: Name: \"%s\" max. number of logins exceeded", | if (gBundles[ac] && gBundles[ac]->open) { |
| auth->info.lnkname, auth->params.authname)); | if (gMaxLoginsCI) { |
| auth->status = AUTH_STATUS_FAIL; | if (!strcasecmp(gBundles[ac]->params.authname, auth->params.authname)) |
| auth->why_fail = AUTH_FAIL_INVALID_LOGIN; | num++; |
| return (-1); | } else { |
| } | if (!strcmp(gBundles[ac]->params.authname, auth->params.authname)) |
| } | num++; |
| return (0); | } |
| | } |
| | } |
| | |
| | if (num >= gMaxLogins) { |
| | Log(LG_ERR | LG_AUTH, ("[%s] AUTH: Name: \"%s\" max. number of logins exceeded", |
| | auth->info.lnkname, auth->params.authname)); |
| | auth->status = AUTH_STATUS_FAIL; |
| | auth->why_fail = AUTH_FAIL_INVALID_LOGIN; |
| | return (-1); |
| | } |
| | } |
| | return (0); |
| } |
} |
| |
|
| /* |
/* |
|
Line 1732 AuthPreChecks(AuthData auth)
|
Line 1746 AuthPreChecks(AuthData auth)
|
| static void |
static void |
| AuthTimeout(void *arg) |
AuthTimeout(void *arg) |
| { |
{ |
| Link l = (Link)arg; | Link l = (Link) arg; |
| |
|
| Log(LG_AUTH, ("[%s] %s: authorization timer expired", Pref(&l->lcp.fsm), Fsm(&l->lcp.fsm))); | Log(LG_AUTH, ("[%s] %s: authorization timer expired", Pref(&l->lcp.fsm), Fsm(&l->lcp.fsm))); |
| AuthStop(l); | AuthStop(l); |
| LcpAuthResult(l, FALSE); | LcpAuthResult(l, FALSE); |
| } |
} |
| |
|
| /* | /* |
| * AuthFailMsg() |
* AuthFailMsg() |
| */ |
*/ |
| |
|
| const char * |
const char * |
| AuthFailMsg(AuthData auth, char *buf, size_t len) |
AuthFailMsg(AuthData auth, char *buf, size_t len) |
| { |
{ |
| const char *mesg; | const char *mesg; |
| |
|
| if (auth->proto == PROTO_CHAP | if (auth->proto == PROTO_CHAP |
| && (auth->alg == CHAP_ALG_MSOFT || auth->alg == CHAP_ALG_MSOFTv2)) { | && (auth->alg == CHAP_ALG_MSOFT || auth->alg == CHAP_ALG_MSOFTv2)) { |
| int mscode; | int mscode; |
| |
|
| if (auth->mschap_error != NULL) { | if (auth->mschap_error != NULL) { |
| strlcpy(buf, auth->mschap_error, len); | strlcpy(buf, auth->mschap_error, len); |
| return(buf); | return (buf); |
| } | } |
| | switch (auth->why_fail) { |
| | case AUTH_FAIL_ACCT_DISABLED: |
| | mscode = MSCHAP_ERROR_ACCT_DISABLED; |
| | mesg = AUTH_MSG_ACCT_DISAB; |
| | break; |
| | case AUTH_FAIL_NO_PERMISSION: |
| | mscode = MSCHAP_ERROR_NO_DIALIN_PERMISSION; |
| | mesg = AUTH_MSG_NOT_ALLOWED; |
| | break; |
| | case AUTH_FAIL_RESTRICTED_HOURS: |
| | mscode = MSCHAP_ERROR_RESTRICTED_LOGON_HOURS; |
| | mesg = AUTH_MSG_RESTR_HOURS; |
| | break; |
| | case AUTH_FAIL_INVALID_PACKET: |
| | case AUTH_FAIL_INVALID_LOGIN: |
| | case AUTH_FAIL_NOT_EXPECTED: |
| | default: |
| | mscode = MSCHAP_ERROR_AUTHENTICATION_FAILURE; |
| | mesg = AUTH_MSG_INVALID; |
| | break; |
| | } |
| |
|
| switch (auth->why_fail) { | /* If we have reply message, send it instead of default. */ |
| case AUTH_FAIL_ACCT_DISABLED: | if (auth->reply_message != NULL) |
| mscode = MSCHAP_ERROR_ACCT_DISABLED; | mesg = auth->reply_message; |
| mesg = AUTH_MSG_ACCT_DISAB; | |
| break; | |
| case AUTH_FAIL_NO_PERMISSION: | |
| mscode = MSCHAP_ERROR_NO_DIALIN_PERMISSION; | |
| mesg = AUTH_MSG_NOT_ALLOWED; | |
| break; | |
| case AUTH_FAIL_RESTRICTED_HOURS: | |
| mscode = MSCHAP_ERROR_RESTRICTED_LOGON_HOURS; | |
| mesg = AUTH_MSG_RESTR_HOURS; | |
| break; | |
| case AUTH_FAIL_INVALID_PACKET: | |
| case AUTH_FAIL_INVALID_LOGIN: | |
| case AUTH_FAIL_NOT_EXPECTED: | |
| default: | |
| mscode = MSCHAP_ERROR_AUTHENTICATION_FAILURE; | |
| mesg = AUTH_MSG_INVALID; | |
| break; | |
| } | |
| |
|
| /* If we have reply message, send it instead of default. */ | snprintf(buf, len, "E=%d R=0 M=%s", mscode, mesg); |
| if (auth->reply_message != NULL) | |
| mesg = auth->reply_message; | |
| |
|
| snprintf(buf, len, "E=%d R=0 M=%s", mscode, mesg); | } else { |
| | |
| } else { | |
| |
|
| if (auth->reply_message != NULL) { | if (auth->reply_message != NULL) { |
| strlcpy(buf, auth->reply_message, len); | strlcpy(buf, auth->reply_message, len); |
| return(buf); | return (buf); |
| } | } |
| switch (auth->why_fail) { |
| switch (auth->why_fail) { | case AUTH_FAIL_ACCT_DISABLED: |
| case AUTH_FAIL_ACCT_DISABLED: | mesg = AUTH_MSG_ACCT_DISAB; |
| mesg = AUTH_MSG_ACCT_DISAB; | break; |
| break; | case AUTH_FAIL_NO_PERMISSION: |
| case AUTH_FAIL_NO_PERMISSION: | mesg = AUTH_MSG_NOT_ALLOWED; |
| mesg = AUTH_MSG_NOT_ALLOWED; | break; |
| break; | case AUTH_FAIL_RESTRICTED_HOURS: |
| case AUTH_FAIL_RESTRICTED_HOURS: | mesg = AUTH_MSG_RESTR_HOURS; |
| mesg = AUTH_MSG_RESTR_HOURS; | break; |
| break; | case AUTH_FAIL_NOT_EXPECTED: |
| case AUTH_FAIL_NOT_EXPECTED: | mesg = AUTH_MSG_NOT_EXPECTED; |
| mesg = AUTH_MSG_NOT_EXPECTED; | break; |
| break; | case AUTH_FAIL_INVALID_PACKET: |
| case AUTH_FAIL_INVALID_PACKET: | mesg = AUTH_MSG_BAD_PACKET; |
| mesg = AUTH_MSG_BAD_PACKET; | break; |
| break; | case AUTH_FAIL_INVALID_LOGIN: |
| case AUTH_FAIL_INVALID_LOGIN: | default: |
| default: | mesg = AUTH_MSG_INVALID; |
| mesg = AUTH_MSG_INVALID; | break; |
| break; | } |
| } | strlcpy(buf, mesg, len); |
| strlcpy(buf, mesg, len); | } |
| } | return (buf); |
| return(buf); | |
| } |
} |
| |
|
| /* | /* |
| * AuthStatusText() |
* AuthStatusText() |
| */ |
*/ |
| |
|
| const char * |
const char * |
| AuthStatusText(int status) |
AuthStatusText(int status) |
| { | { |
| switch (status) { | switch (status) { |
| case AUTH_STATUS_UNDEF: | case AUTH_STATUS_UNDEF: |
| return "undefined"; | return "undefined"; |
| |
|
| case AUTH_STATUS_SUCCESS: | case AUTH_STATUS_SUCCESS: |
| return "authenticated"; | return "authenticated"; |
| |
|
| case AUTH_STATUS_FAIL: | case AUTH_STATUS_FAIL: |
| return "failed"; | return "failed"; |
| |
|
| case AUTH_STATUS_BUSY: | case AUTH_STATUS_BUSY: |
| return "busy"; | return "busy"; |
| |
|
| default: | default: |
| return "INCORRECT STATUS"; | return "INCORRECT STATUS"; |
| } | } |
| } |
} |
| |
|
| /* | /* |
| * AuthMPPEPolicyname() |
* AuthMPPEPolicyname() |
| */ |
*/ |
| |
|
| const char * |
const char * |
| AuthMPPEPolicyname(int policy) | AuthMPPEPolicyname(int policy) |
| { |
{ |
| switch(policy) { | switch (policy) { |
| case MPPE_POLICY_ALLOWED: | case MPPE_POLICY_ALLOWED: |
| return "Allowed"; | return "Allowed"; |
| case MPPE_POLICY_REQUIRED: | case MPPE_POLICY_REQUIRED: |
| return "Required"; | return "Required"; |
| case MPPE_POLICY_NONE: | case MPPE_POLICY_NONE: |
| return "Not available"; | return "Not available"; |
| default: | default: |
| return "Unknown Policy"; | return "Unknown Policy"; |
| } | } |
| |
|
| } |
} |
| |
|
| /* | /* |
| * AuthMPPETypesname() |
* AuthMPPETypesname() |
| */ |
*/ |
| |
|
| const char * |
const char * |
| AuthMPPETypesname(int types, char *buf, size_t len) | AuthMPPETypesname(int types, char *buf, size_t len) |
| { |
{ |
| if (types == 0) { | if (types == 0) { |
| sprintf(buf, "no encryption required"); | strlcpy(buf, "no encryption required", len); |
| return (buf); | return (buf); |
| } | } |
| | buf[0] = 0; |
| | if (types & MPPE_TYPE_40BIT) |
| | strlcpy(buf, "40 ", len); |
| | if (types & MPPE_TYPE_56BIT) |
| | strlcat(buf, "56 ", len); |
| | if (types & MPPE_TYPE_128BIT) |
| | strlcat(buf, "128 ", len); |
| |
|
| buf[0]=0; | if (strlen(buf) == 0) { |
| if (types & MPPE_TYPE_40BIT) sprintf (buf, "40 "); | strlcpy(buf, "unknown types", len); |
| if (types & MPPE_TYPE_56BIT) sprintf (&buf[strlen(buf)], "56 "); | } else { |
| if (types & MPPE_TYPE_128BIT) sprintf (&buf[strlen(buf)], "128 "); | strlcat(buf, "bit", len); |
| | } |
| |
|
| if (strlen(buf) == 0) { | return (buf); |
| sprintf (buf, "unknown types"); | |
| } else { | |
| sprintf (&buf[strlen(buf)], "bit"); | |
| } | |
| |
| return (buf); | |
| } |
} |
| |
|
| /* |
/* |
|
Line 1897 AuthMPPETypesname(int types, char *buf, size_t len)
|
Line 1911 AuthMPPETypesname(int types, char *buf, size_t len)
|
| * -1 on error (can't fork, no data read, whatever) |
* -1 on error (can't fork, no data read, whatever) |
| */ |
*/ |
| static int |
static int |
| AuthGetExternalPassword(char * extcmd, char *authname, char *password, size_t passlen) | AuthGetExternalPassword(const char *extcmd, char *authname, char *password, size_t passlen) |
| { |
{ |
| char cmd[AUTH_MAX_PASSWORD + 5 + AUTH_MAX_AUTHNAME]; | char cmd[AUTH_MAX_PASSWORD + 5 + AUTH_MAX_AUTHNAME]; |
| int ok = 0; | int ok = 0; |
| FILE *fp; | FILE *fp; |
| int len; | int len; |
| |
|
| snprintf(cmd, sizeof(cmd), "%s %s", extcmd, authname); | snprintf(cmd, sizeof(cmd), "%s %s", extcmd, authname); |
| Log(LG_AUTH, ("Invoking external auth program: '%s'", cmd)); | Log(LG_AUTH, ("Invoking external auth program: '%s'", cmd)); |
| if ((fp = popen(cmd, "r")) == NULL) { | if ((fp = popen(cmd, "r")) == NULL) { |
| Perror("Popen"); | Perror("Popen"); |
| return (-1); | return (-1); |
| } | } |
| if (fgets(password, passlen, fp) != NULL) { | if (fgets(password, passlen, fp) != NULL) { |
| len = strlen(password); /* trim trailing newline */ | len = strlen(password); /* trim trailing newline */ |
| if (len > 0 && password[len - 1] == '\n') | if (len > 0 && password[len - 1] == '\n') |
| password[len - 1] = '\0'; | password[len - 1] = '\0'; |
| ok = (password[0] != '\0'); | ok = (password[0] != '\0'); |
| } else { | } else { |
| if (ferror(fp)) | if (ferror(fp)) |
| Perror("Error reading from external auth program"); | Perror("Error reading from external auth program"); |
| } | } |
| if (!ok) | if (!ok) |
| Log(LG_AUTH, ("External auth program failed for user \"%s\"", | Log(LG_AUTH, ("External auth program failed for user \"%s\"", |
| authname)); | authname)); |
| pclose(fp); | pclose(fp); |
| return (ok ? 0 : -1); | return (ok ? 0 : -1); |
| } |
} |
| |
|
| /* |
/* |
|
Line 1933 AuthGetExternalPassword(char * extcmd, char *authname,
|
Line 1947 AuthGetExternalPassword(char * extcmd, char *authname,
|
| static const char * |
static const char * |
| AuthCode(int proto, u_char code, char *buf, size_t len) |
AuthCode(int proto, u_char code, char *buf, size_t len) |
| { |
{ |
| switch (proto) { | switch (proto) { |
| case PROTO_EAP: | case PROTO_EAP: |
| return EapCode(code, buf, len); | return EapCode(code, buf, len); |
| |
|
| case PROTO_CHAP: | case PROTO_CHAP: |
| return ChapCode(code, buf, len); | return ChapCode(code, buf, len); |
| |
|
| case PROTO_PAP: | case PROTO_PAP: |
| return PapCode(code, buf, len); | return PapCode(code, buf, len); |
| |
|
| default: | default: |
| snprintf(buf, len, "code %d", code); | snprintf(buf, len, "code %d", code); |
| return(buf); | return (buf); |
| } | } |
| } |
} |
| |
|
| |
|
|
Line 1955 AuthCode(int proto, u_char code, char *buf, size_t len
|
Line 1969 AuthCode(int proto, u_char code, char *buf, size_t len
|
| */ |
*/ |
| |
|
| static int |
static int |
| AuthSetCommand(Context ctx, int ac, char *av[], void *arg) | AuthSetCommand(Context ctx, int ac, const char *const av[], const void *arg) |
| { |
{ |
| AuthConf const autc = &ctx->lnk->lcp.auth.conf; | AuthConf const autc = &ctx->lnk->lcp.auth.conf; |
| int val; | int val; |
| |
|
| if (ac == 0) | if (ac == 0) |
| return(-1); | return (-1); |
| |
|
| switch ((intptr_t)arg) { | switch ((intptr_t)arg) { |
| |
|
| case SET_AUTHNAME: | case SET_AUTHNAME: |
| strlcpy(autc->authname, *av, sizeof(autc->authname)); | strlcpy(autc->authname, *av, sizeof(autc->authname)); |
| break; | break; |
| |
|
| case SET_PASSWORD: | case SET_PASSWORD: |
| strlcpy(autc->password, *av, sizeof(autc->password)); | strlcpy(autc->password, *av, sizeof(autc->password)); |
| break; | break; |
| | |
| case SET_EXTAUTH_SCRIPT: | |
| Freee(autc->extauth_script); | |
| autc->extauth_script = Mstrdup(MB_AUTH, *av); | |
| break; | |
| | |
| case SET_EXTACCT_SCRIPT: | |
| Freee(autc->extacct_script); | |
| autc->extacct_script = Mstrdup(MB_AUTH, *av); | |
| break; | |
| | |
| case SET_MAX_LOGINS: | |
| gMaxLogins = atoi(av[0]); | |
| if (ac >= 2 && strcasecmp(av[1], "ci") == 0) { | |
| gMaxLoginsCI = 1; | |
| } else { | |
| gMaxLoginsCI = 0; | |
| } | |
| break; | |
| | |
| case SET_ACCT_UPDATE: | |
| val = atoi(*av); | |
| if (val < 0) | |
| Error("Update interval must be positive."); | |
| else | |
| autc->acct_update = val; | |
| break; | |
| |
|
| case SET_ACCT_UPDATE_LIMIT_IN: | case SET_EXTAUTH_SCRIPT: |
| case SET_ACCT_UPDATE_LIMIT_OUT: | Freee(autc->extauth_script); |
| val = atoi(*av); | autc->extauth_script = Mstrdup(MB_AUTH, *av); |
| if (val < 0) | break; |
| Error("Update suppression limit must be positive."); | |
| else { | |
| if ((intptr_t)arg == SET_ACCT_UPDATE_LIMIT_IN) | |
| autc->acct_update_lim_recv = val; | |
| else | |
| autc->acct_update_lim_xmit = val; | |
| } | |
| break; | |
| |
|
| case SET_TIMEOUT: | case SET_EXTACCT_SCRIPT: |
| val = atoi(*av); | Freee(autc->extacct_script); |
| if (val <= 20) | autc->extacct_script = Mstrdup(MB_AUTH, *av); |
| Error("Authorization timeout must be greater then 20."); | break; |
| else | |
| autc->timeout = val; | |
| break; | |
| | |
| case SET_ACCEPT: | |
| AcceptCommand(ac, av, &autc->options, gConfList); | |
| break; | |
| |
|
| case SET_DENY: | case SET_MAX_LOGINS: |
| DenyCommand(ac, av, &autc->options, gConfList); | gMaxLogins = (unsigned)atoi(av[0]); |
| break; | if (ac >= 2 && strcasecmp(av[1], "ci") == 0) { |
| | gMaxLoginsCI = 1; |
| | } else { |
| | gMaxLoginsCI = 0; |
| | } |
| | break; |
| |
|
| case SET_ENABLE: | case SET_ACCT_UPDATE: |
| EnableCommand(ac, av, &autc->options, gConfList); | val = atoi(*av); |
| break; | if (val < 0) |
| | Error("Update interval must be positive."); |
| | else |
| | autc->acct_update = val; |
| | break; |
| |
|
| case SET_DISABLE: | case SET_ACCT_UPDATE_LIMIT_IN: |
| DisableCommand(ac, av, &autc->options, gConfList); | case SET_ACCT_UPDATE_LIMIT_OUT: |
| break; | val = atoi(*av); |
| | if (val < 0) |
| | Error("Update suppression limit must be positive."); |
| | else { |
| | if ((intptr_t)arg == SET_ACCT_UPDATE_LIMIT_IN) |
| | autc->acct_update_lim_recv = val; |
| | else |
| | autc->acct_update_lim_xmit = val; |
| | } |
| | break; |
| |
|
| case SET_YES: | case SET_TIMEOUT: |
| YesCommand(ac, av, &autc->options, gConfList); | val = atoi(*av); |
| break; | if (val <= 20) |
| | Error("Authorization timeout must be greater then 20."); |
| | else |
| | autc->timeout = val; |
| | break; |
| |
|
| case SET_NO: | case SET_ACCEPT: |
| NoCommand(ac, av, &autc->options, gConfList); | AcceptCommand(ac, av, &autc->options, gConfList); |
| break; | break; |
| |
|
| default: | case SET_DENY: |
| assert(0); | DenyCommand(ac, av, &autc->options, gConfList); |
| } | break; |
| |
|
| return(0); | case SET_ENABLE: |
| | EnableCommand(ac, av, &autc->options, gConfList); |
| | break; |
| | |
| | case SET_DISABLE: |
| | DisableCommand(ac, av, &autc->options, gConfList); |
| | break; |
| | |
| | case SET_YES: |
| | YesCommand(ac, av, &autc->options, gConfList); |
| | break; |
| | |
| | case SET_NO: |
| | NoCommand(ac, av, &autc->options, gConfList); |
| | break; |
| | |
| | default: |
| | assert(0); |
| | } |
| | |
| | return (0); |
| } |
} |
| |
|
| /* |
/* |
| * AuthExternal() |
* AuthExternal() |
| * | * |
| * Authenticate via call external script extauth-script |
* Authenticate via call external script extauth-script |
| */ |
*/ |
| | |
| static int |
static int |
| AuthExternal(AuthData auth) |
AuthExternal(AuthData auth) |
| { |
{ |
| char line[256]; | char line[256]; |
| FILE *fp; | FILE *fp; |
| char *attr, *val; | char *attr, *val; |
| int len; | int len; |
| | |
| if (!auth->conf.extauth_script || !auth->conf.extauth_script[0]) { | |
| Log(LG_ERR, ("[%s] Ext-auth: Script not specified!", | |
| auth->info.lnkname)); | |
| return (-1); | |
| } | |
| if (strchr(auth->params.authname, '\'') || | |
| strchr(auth->params.authname, '\n')) { | |
| Log(LG_ERR, ("[%s] Ext-auth: Denied character in USER_NAME!", | |
| auth->info.lnkname)); | |
| return (-1); | |
| } | |
| snprintf(line, sizeof(line), "%s '%s'", | |
| auth->conf.extauth_script, auth->params.authname); | |
| Log(LG_AUTH, ("[%s] Ext-auth: Invoking auth program: '%s'", | |
| auth->info.lnkname, line)); | |
| if ((fp = popen(line, "r+")) == NULL) { | |
| Perror("Popen"); | |
| return (-1); | |
| } | |
| |
|
| /* SENDING REQUEST */ | if (!auth->conf.extauth_script || !auth->conf.extauth_script[0]) { |
| fprintf(fp, "USER_NAME:%s\n", auth->params.authname); | Log(LG_ERR, ("[%s] Ext-auth: Script not specified!", |
| fprintf(fp, "AUTH_TYPE:%s", ProtoName(auth->proto)); | auth->info.lnkname)); |
| if (auth->proto == PROTO_CHAP) { | return (-1); |
| switch (auth->alg) { | |
| case CHAP_ALG_MD5: | |
| fprintf(fp, " MD5\n"); | |
| break; | |
| case CHAP_ALG_MSOFT: | |
| fprintf(fp, " MSOFT\n"); | |
| break; | |
| case CHAP_ALG_MSOFTv2: | |
| fprintf(fp, " MSOFTv2\n"); | |
| break; | |
| default: | |
| fprintf(fp, " 0x%02x\n", auth->alg); | |
| break; | |
| } |
} |
| } else | if (strchr(auth->params.authname, '\'') || |
| fprintf(fp, "\n"); | strchr(auth->params.authname, '\n')) { |
| | Log(LG_ERR, ("[%s] Ext-auth: Denied character in USER_NAME!", |
| | auth->info.lnkname)); |
| | return (-1); |
| | } |
| | snprintf(line, sizeof(line), "%s '%s'", |
| | auth->conf.extauth_script, auth->params.authname); |
| | Log(LG_AUTH, ("[%s] Ext-auth: Invoking auth program: '%s'", |
| | auth->info.lnkname, line)); |
| | if ((fp = popen(line, "r+")) == NULL) { |
| | Perror("Popen"); |
| | return (-1); |
| | } |
| | /* SENDING REQUEST */ |
| | fprintf(fp, "USER_NAME:%s\n", auth->params.authname); |
| | fprintf(fp, "AUTH_TYPE:%s", ProtoName(auth->proto)); |
| | if (auth->proto == PROTO_CHAP) { |
| | switch (auth->alg) { |
| | case CHAP_ALG_MD5: |
| | fprintf(fp, " MD5\n"); |
| | break; |
| | case CHAP_ALG_MSOFT: |
| | fprintf(fp, " MSOFT\n"); |
| | break; |
| | case CHAP_ALG_MSOFTv2: |
| | fprintf(fp, " MSOFTv2\n"); |
| | break; |
| | default: |
| | fprintf(fp, " 0x%02x\n", auth->alg); |
| | break; |
| | } |
| | } else |
| | fprintf(fp, "\n"); |
| |
|
| if (auth->proto == PROTO_PAP) | if (auth->proto == PROTO_PAP) |
| fprintf(fp, "USER_PASSWORD:%s\n", auth->params.pap.peer_pass); | fprintf(fp, "USER_PASSWORD:%s\n", auth->params.pap.peer_pass); |
| |
|
| fprintf(fp, "ACCT_SESSION_ID:%s\n", auth->info.session_id); | fprintf(fp, "ACCT_SESSION_ID:%s\n", auth->info.session_id); |
| fprintf(fp, "LINK:%s\n", auth->info.lnkname); | fprintf(fp, "LINK:%s\n", auth->info.lnkname); |
| fprintf(fp, "NAS_PORT:%d\n", auth->info.linkID); | fprintf(fp, "NAS_PORT:%d\n", auth->info.linkID); |
| fprintf(fp, "NAS_PORT_TYPE:%s\n", auth->info.phys_type->name); | fprintf(fp, "NAS_PORT_TYPE:%s\n", auth->info.phys_type->name); |
| fprintf(fp, "CALLING_STATION_ID:%s\n", auth->params.callingnum); | fprintf(fp, "CALLING_STATION_ID:%s\n", auth->params.callingnum); |
| fprintf(fp, "CALLED_STATION_ID:%s\n", auth->params.callednum); | fprintf(fp, "CALLED_STATION_ID:%s\n", auth->params.callednum); |
| fprintf(fp, "SELF_NAME:%s\n", auth->params.selfname); | fprintf(fp, "SELF_NAME:%s\n", auth->params.selfname); |
| fprintf(fp, "PEER_NAME:%s\n", auth->params.peername); | fprintf(fp, "PEER_NAME:%s\n", auth->params.peername); |
| fprintf(fp, "SELF_ADDR:%s\n", auth->params.selfaddr); | fprintf(fp, "SELF_ADDR:%s\n", auth->params.selfaddr); |
| fprintf(fp, "PEER_ADDR:%s\n", auth->params.peeraddr); | fprintf(fp, "PEER_ADDR:%s\n", auth->params.peeraddr); |
| fprintf(fp, "PEER_PORT:%s\n", auth->params.peerport); | fprintf(fp, "PEER_PORT:%s\n", auth->params.peerport); |
| fprintf(fp, "PEER_MAC_ADDR:%s\n", auth->params.peermacaddr); | fprintf(fp, "PEER_MAC_ADDR:%s\n", auth->params.peermacaddr); |
| fprintf(fp, "PEER_IFACE:%s\n", auth->params.peeriface); | fprintf(fp, "PEER_IFACE:%s\n", auth->params.peeriface); |
| fprintf(fp, "PEER_IDENT:%s\n", auth->info.peer_ident); | fprintf(fp, "PEER_IDENT:%s\n", auth->info.peer_ident); |
| | |
| |
|
| /* REQUEST DONE */ |
|
| fprintf(fp, "\n"); |
|
| |
|
| /* REPLY PROCESSING */ | /* REQUEST DONE */ |
| auth->status = AUTH_STATUS_FAIL; | fprintf(fp, "\n"); |
| while (fgets(line, sizeof(line), fp)) { | |
| /* trim trailing newline */ | |
| len = strlen(line); | |
| if (len > 0 && line[len - 1] == '\n') { | |
| line[len - 1] = '\0'; | |
| len--; | |
| } | |
| |
|
| /* Empty line is the end marker */ | /* REPLY PROCESSING */ |
| if (len == 0) | auth->status = AUTH_STATUS_FAIL; |
| break; | while (fgets(line, sizeof(line), fp)) { |
| | /* trim trailing newline */ |
| | len = strlen(line); |
| | if (len > 0 && line[len - 1] == '\n') { |
| | line[len - 1] = '\0'; |
| | len--; |
| | } |
| | /* Empty line is the end marker */ |
| | if (len == 0) |
| | break; |
| |
|
| /* split line on attr:value */ | /* split line on attr:value */ |
| val = line; | val = line; |
| attr = strsep(&val, ":"); | attr = strsep(&val, ":"); |
| |
|
| /* Log data w/o password */ | /* Log data w/o password */ |
| if (strcmp(attr, "USER_PASSWORD") != 0) { | if (strcmp(attr, "USER_PASSWORD") != 0) { |
| Log(LG_AUTH2, ("[%s] Ext-auth: attr:'%s', value:'%s'", | Log(LG_AUTH2, ("[%s] Ext-auth: attr:'%s', value:'%s'", |
| auth->info.lnkname, attr, val)); | auth->info.lnkname, attr, val)); |
| } else { | } else { |
| Log(LG_AUTH2, ("[%s] Ext-auth: attr:'%s', value:'XXX'", | Log(LG_AUTH2, ("[%s] Ext-auth: attr:'%s', value:'XXX'", |
| auth->info.lnkname, attr)); | auth->info.lnkname, attr)); |
| } | } |
| | |
| if (strcmp(attr, "RESULT") == 0) { | |
| if (strcmp(val, "SUCCESS") == 0) { | |
| auth->status = AUTH_STATUS_SUCCESS; | |
| } else if (strcmp(val, "UNDEF") == 0) { | |
| auth->status = AUTH_STATUS_UNDEF; | |
| } else | |
| auth->status = AUTH_STATUS_FAIL; | |
| |
|
| } else if (strcmp(attr, "USER_NAME") == 0) { | if (strcmp(attr, "RESULT") == 0) { |
| strlcpy(auth->params.authname, val, sizeof(auth->params.authname)); | if (strcmp(val, "SUCCESS") == 0) { |
| | auth->status = AUTH_STATUS_SUCCESS; |
| | } else if (strcmp(val, "UNDEF") == 0) { |
| | auth->status = AUTH_STATUS_UNDEF; |
| | } else |
| | auth->status = AUTH_STATUS_FAIL; |
| |
|
| } else if (strcmp(attr, "USER_PASSWORD") == 0) { | } else if (strcmp(attr, "USER_NAME") == 0) { |
| strlcpy(auth->params.password, val, sizeof(auth->params.password)); | strlcpy(auth->params.authname, val, sizeof(auth->params.authname)); |
| |
|
| } else if (strcmp(attr, "USER_NT_HASH") == 0) { | } else if (strcmp(attr, "USER_PASSWORD") == 0) { |
| if (strlen(val) != 32) { | strlcpy(auth->params.password, val, sizeof(auth->params.password)); |
| Log(LG_AUTH, ("[%s] Ext-auth: Incorrect USER_NT_HASH length", auth->info.lnkname)); | |
| } else { | |
| u_char *bin = Hex2Bin(val); | |
| memcpy(auth->params.msoft.nt_hash, bin, sizeof(auth->params.msoft.nt_hash)); | |
| Freee(bin); | |
| NTPasswordHashHash(auth->params.msoft.nt_hash, auth->params.msoft.nt_hash_hash); | |
| auth->params.msoft.has_nt_hash = TRUE; | |
| } | |
| |
|
| } else if (strcmp(attr, "USER_LM_HASH") == 0) { | } else if (strcmp(attr, "USER_NT_HASH") == 0) { |
| if (strlen(val) != 32) { | if (strlen(val) != 32) { |
| Log(LG_AUTH, ("[%s] Ext-auth: Incorrect USER_LM_HASH length", auth->info.lnkname)); | Log(LG_AUTH, ("[%s] Ext-auth: Incorrect USER_NT_HASH length", auth->info.lnkname)); |
| } else { | } else { |
| u_char *bin = Hex2Bin(val); | u_char *bin = Hex2Bin(val); |
| memcpy(auth->params.msoft.lm_hash, bin, sizeof(auth->params.msoft.lm_hash)); | |
| Freee(bin); | |
| auth->params.msoft.has_lm_hash = TRUE; | |
| } | |
| |
|
| } else if (strcmp(attr, "FRAMED_IP_ADDRESS") == 0) { | memcpy(auth->params.msoft.nt_hash, bin, sizeof(auth->params.msoft.nt_hash)); |
| auth->params.range_valid = | Freee(bin); |
| ParseRange(val, &auth->params.range, ALLOW_IPV4); | NTPasswordHashHash(auth->params.msoft.nt_hash, auth->params.msoft.nt_hash_hash); |
| | auth->params.msoft.has_nt_hash = TRUE; |
| | } |
| |
|
| } else if (strcmp(attr, "PRIMARY_DNS_SERVER") == 0) { | } else if (strcmp(attr, "USER_LM_HASH") == 0) { |
| inet_pton(AF_INET, val, &auth->params.peer_dns[0]); | if (strlen(val) != 32) { |
| | Log(LG_AUTH, ("[%s] Ext-auth: Incorrect USER_LM_HASH length", auth->info.lnkname)); |
| | } else { |
| | u_char *bin = Hex2Bin(val); |
| |
|
| } else if (strcmp(attr, "SECONDARY_DNS_SERVER") == 0) { | memcpy(auth->params.msoft.lm_hash, bin, sizeof(auth->params.msoft.lm_hash)); |
| inet_pton(AF_INET, val, &auth->params.peer_dns[1]); | Freee(bin); |
| | auth->params.msoft.has_lm_hash = TRUE; |
| | } |
| |
|
| } else if (strcmp(attr, "PRIMARY_NBNS_SERVER") == 0) { | } else if (strcmp(attr, "FRAMED_IP_ADDRESS") == 0) { |
| inet_pton(AF_INET, val, &auth->params.peer_nbns[0]); | auth->params.range_valid = |
| | ParseRange(val, &auth->params.range, ALLOW_IPV4); |
| |
|
| } else if (strcmp(attr, "SECONDARY_NBNS_SERVER") == 0) { | } else if (strcmp(attr, "PRIMARY_DNS_SERVER") == 0) { |
| inet_pton(AF_INET, val, &auth->params.peer_nbns[1]); | inet_pton(AF_INET, val, &auth->params.peer_dns[0]); |
| |
|
| } else if (strcmp(attr, "FRAMED_ROUTE") == 0) { | } else if (strcmp(attr, "SECONDARY_DNS_SERVER") == 0) { |
| struct u_range range; | inet_pton(AF_INET, val, &auth->params.peer_dns[1]); |
| |
|
| if (!ParseRange(val, &range, ALLOW_IPV4)) { | } else if (strcmp(attr, "PRIMARY_NBNS_SERVER") == 0) { |
| Log(LG_AUTH, ("[%s] Ext-auth: FRAMED_ROUTE: Bad route \"%s\"", | inet_pton(AF_INET, val, &auth->params.peer_nbns[0]); |
| auth->info.lnkname, val)); | |
| } else { | |
| struct ifaceroute *r, *r1; | |
| int j; | |
| |
|
| r = Malloc(MB_AUTH, sizeof(struct ifaceroute)); | } else if (strcmp(attr, "SECONDARY_NBNS_SERVER") == 0) { |
| r->dest = range; | inet_pton(AF_INET, val, &auth->params.peer_nbns[1]); |
| r->ok = 0; | |
| j = 0; | |
| SLIST_FOREACH(r1, &auth->params.routes, next) { | |
| if (!u_rangecompare(&r->dest, &r1->dest)) { | |
| Log(LG_AUTH, ("[%s] Ext-auth: Duplicate route", auth->info.lnkname)); | |
| j = 1; | |
| } | |
| }; | |
| if (j == 0) { | |
| SLIST_INSERT_HEAD(&auth->params.routes, r, next); | |
| } else { | |
| Freee(r); | |
| } | |
| } | |
| |
|
| } else if (strcmp(attr, "FRAMED_IPV6_ROUTE") == 0) { | } else if (strcmp(attr, "FRAMED_ROUTE") == 0) { |
| struct u_range range; | struct u_range range; |
| |
|
| if (!ParseRange(val, &range, ALLOW_IPV6)) { | if (!ParseRange(val, &range, ALLOW_IPV4)) { |
| Log(LG_AUTH, ("[%s] Ext-auth: FRAMED_IPV6_ROUTE: Bad route \"%s\"", | Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: FRAMED_ROUTE: Bad route \"%s\"", |
| auth->info.lnkname, val)); | auth->info.lnkname, val)); |
| } else { | } else { |
| struct ifaceroute *r, *r1; | struct ifaceroute *r, *r1; |
| int j; | int j; |
| |
|
| r = Malloc(MB_AUTH, sizeof(struct ifaceroute)); | r = Malloc(MB_AUTH, sizeof(struct ifaceroute)); |
| r->dest = range; | r->dest = range; |
| r->ok = 0; | r->ok = 0; |
| j = 0; | j = 0; |
| SLIST_FOREACH(r1, &auth->params.routes, next) { | SLIST_FOREACH(r1, &auth->params.routes, next) { |
| if (!u_rangecompare(&r->dest, &r1->dest)) { | if (!u_rangecompare(&r->dest, &r1->dest)) { |
| Log(LG_AUTH, ("[%s] Ext-auth: Duplicate route", auth->info.lnkname)); | Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: Duplicate route", |
| j = 1; | auth->info.lnkname)); |
| } | j = 1; |
| }; | } |
| if (j == 0) { | }; |
| SLIST_INSERT_HEAD(&auth->params.routes, r, next); | if (j == 0) { |
| } else { | SLIST_INSERT_HEAD(&auth->params.routes, r, next); |
| Freee(r); | } else { |
| } | Freee(r); |
| } | } |
| | } |
| |
|
| } else if (strcmp(attr, "SESSION_TIMEOUT") == 0) { | } else if (strcmp(attr, "FRAMED_IPV6_ROUTE") == 0) { |
| auth->params.session_timeout = atoi(val); | struct u_range range; |
| |
|
| } else if (strcmp(attr, "IDLE_TIMEOUT") == 0) { | if (!ParseRange(val, &range, ALLOW_IPV6)) { |
| auth->params.idle_timeout = atoi(val); | Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: FRAMED_IPV6_ROUTE: Bad route \"%s\"", |
| | auth->info.lnkname, val)); |
| | } else { |
| | struct ifaceroute *r, *r1; |
| | int j; |
| |
|
| } else if (strcmp(attr, "ACCT_INTERIM_INTERVAL") == 0) { | r = Malloc(MB_AUTH, sizeof(struct ifaceroute)); |
| auth->params.acct_update = atoi(val); | r->dest = range; |
| | r->ok = 0; |
| | j = 0; |
| | SLIST_FOREACH(r1, &auth->params.routes, next) { |
| | if (!u_rangecompare(&r->dest, &r1->dest)) { |
| | Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: Duplicate route", |
| | auth->info.lnkname)); |
| | j = 1; |
| | } |
| | }; |
| | if (j == 0) { |
| | SLIST_INSERT_HEAD(&auth->params.routes, r, next); |
| | } else { |
| | Freee(r); |
| | } |
| | } |
| |
|
| } else if (strcmp(attr, "ACCT_INTERIM_LIM_RECV") == 0) { | } else if (strcmp(attr, "SESSION_TIMEOUT") == 0) { |
| auth->params.acct_update_lim_recv = atoi(val); | auth->params.session_timeout = atoi(val); |
| |
|
| } else if (strcmp(attr, "ACCT_INTERIM_LIM_XMIT") == 0) { | } else if (strcmp(attr, "IDLE_TIMEOUT") == 0) { |
| auth->params.acct_update_lim_xmit = atoi(val); | auth->params.idle_timeout = atoi(val); |
| |
|
| } else if (strcmp(attr, "FRAMED_MTU") == 0) { | } else if (strcmp(attr, "ACCT_INTERIM_INTERVAL") == 0) { |
| auth->params.mtu = atoi(val); | auth->params.acct_update = atoi(val); |
| |
|
| } else if (strcmp(attr, "FRAMED_COMPRESSION") == 0) { | } else if (strcmp(attr, "ACCT_INTERIM_LIM_RECV") == 0) { |
| if (atoi(val) == 1) | auth->params.acct_update_lim_recv = atoi(val); |
| auth->params.vjc_enable = 1; | |
| |
|
| } else if (strcmp(attr, "FRAMED_POOL") == 0) { | } else if (strcmp(attr, "ACCT_INTERIM_LIM_XMIT") == 0) { |
| strlcpy(auth->params.ippool, val, sizeof(auth->params.ippool)); | auth->params.acct_update_lim_xmit = atoi(val); |
| |
|
| } else if (strcmp(attr, "REPLY_MESSAGE") == 0) { | } else if (strcmp(attr, "FRAMED_MTU") == 0) { |
| Freee(auth->reply_message); | auth->params.mtu = atoi(val); |
| auth->reply_message = Mstrdup(MB_AUTH, val); | |
| |
|
| } else if (strcmp(attr, "MS_CHAP_ERROR") == 0) { | } else if (strcmp(attr, "FRAMED_COMPRESSION") == 0) { |
| Freee(auth->mschap_error); | if (atoi(val) == 1) |
| /* "E=%d R=0 M=%s" */ | auth->params.vjc_enable = 1; |
| auth->mschap_error = Mstrdup(MB_AUTH, val); | |
| |
|
| } else if (strcmp(attr, "MPD_ACTION") == 0) { | } else if (strcmp(attr, "FRAMED_POOL") == 0) { |
| strlcpy(auth->params.action, val, sizeof(auth->params.action)); | strlcpy(auth->params.ippool, val, sizeof(auth->params.ippool)); |
| |
|
| } else if (strcmp(attr, "MPD_IFACE_NAME") == 0) { | } else if (strcmp(attr, "REPLY_MESSAGE") == 0) { |
| strlcpy(auth->params.ifname, val, sizeof(auth->params.ifname)); | Freee(auth->reply_message); |
| | auth->reply_message = Mstrdup(MB_AUTH, val); |
| |
|
| |
} else if (strcmp(attr, "MS_CHAP_ERROR") == 0) { |
| |
Freee(auth->mschap_error); |
| |
/* "E=%d R=0 M=%s" */ |
| |
auth->mschap_error = Mstrdup(MB_AUTH, val); |
| |
|
| |
} else if (strcmp(attr, "MPD_ACTION") == 0) { |
| |
strlcpy(auth->params.action, val, sizeof(auth->params.action)); |
| |
|
| |
} else if (strcmp(attr, "MPD_IFACE_NAME") == 0) { |
| |
strlcpy(auth->params.ifname, val, sizeof(auth->params.ifname)); |
| |
|
| #ifdef SIOCSIFDESCR |
#ifdef SIOCSIFDESCR |
| } else if (strcmp(attr, "MPD_IFACE_DESCR") == 0) { | } else if (strcmp(attr, "MPD_IFACE_DESCR") == 0) { |
| Freee(auth->params.ifdescr); | Freee(auth->params.ifdescr); |
| auth->params.ifdescr = Mstrdup(MB_AUTH, val); | auth->params.ifdescr = Mstrdup(MB_AUTH, val); |
| #endif /* SIOCSIFDESCR */ | #endif /* SIOCSIFDESCR */ |
| #ifdef SIOCAIFGROUP |
#ifdef SIOCAIFGROUP |
| } else if (strcmp(attr, "MPD_IFACE_GROUP") == 0) { | } else if (strcmp(attr, "MPD_IFACE_GROUP") == 0) { |
| strlcpy(auth->params.ifgroup, val, sizeof(auth->params.ifgroup)); | strlcpy(auth->params.ifgroup, val, sizeof(auth->params.ifgroup)); |
| #endif |
#endif |
| #if defined(USE_IPFW) || defined(USE_NG_BPF) |
#if defined(USE_IPFW) || defined(USE_NG_BPF) |
| } else if (strncmp(attr, "MPD_", 4) == 0) { | } else if (strncmp(attr, "MPD_", 4) == 0) { |
| struct acl **acls, *acls1; | struct acl **acls, *acls1; |
| char *acl1, *acl2, *acl3; | char *acl1, *acl2, *acl3; |
| int i; | int i; |
| | |
| acl1 = NULL; | acl1 = NULL; |
| acls = NULL; | acls = NULL; |
| #ifdef USE_IPFW |
#ifdef USE_IPFW |
| if (strcmp(attr, "MPD_RULE") == 0) { | if (strcmp(attr, "MPD_RULE") == 0) { |
| acl1 = val; | acl1 = val; |
| acls = &(auth->params.acl_rule); | acls = &(auth->params.acl_rule); |
| } else if (strcmp(attr, "MPD_PIPE") == 0) { | } else if (strcmp(attr, "MPD_PIPE") == 0) { |
| acl1 = val; | acl1 = val; |
| acls = &(auth->params.acl_pipe); | acls = &(auth->params.acl_pipe); |
| } else if (strcmp(attr, "MPD_QUEUE") == 0) { | } else if (strcmp(attr, "MPD_QUEUE") == 0) { |
| acl1 = val; | acl1 = val; |
| acls = &(auth->params.acl_queue); | acls = &(auth->params.acl_queue); |
| } else if (strcmp(attr, "MPD_TABLE") == 0) { | } else if (strcmp(attr, "MPD_TABLE") == 0) { |
| acl1 = val; | acl1 = val; |
| acls = &(auth->params.acl_table); | acls = &(auth->params.acl_table); |
| } else if (strcmp(attr, "MPD_TABLE_STATIC") == 0) { | } else if (strcmp(attr, "MPD_TABLE_STATIC") == 0) { |
| acl1 = val; | acl1 = val; |
| acls = &(auth->params.acl_table); | acls = &(auth->params.acl_table); |
| } else | } else |
| #endif /* USE_IPFW */ | #endif /* USE_IPFW */ |
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| if (strcmp(attr, "MPD_FILTER") == 0) { | if (strcmp(attr, "MPD_FILTER") == 0) { |
| acl1 = val; | acl1 = val; |
| acl2 = strsep(&acl1, "#"); | acl2 = strsep(&acl1, "#"); |
| i = atol(acl2); | i = atol(acl2); |
| if (i <= 0 || i > ACL_FILTERS) { | if (i <= 0 || i > ACL_FILTERS) { |
| Log(LG_ERR, ("[%s] Ext-auth: wrong filter number: %i", | Log(LG_ERR, ("[%s] Ext-auth: wrong filter number: %i", |
| auth->info.lnkname, i)); | auth->info.lnkname, i)); |
| continue; | continue; |
| } | } |
| acls = &(auth->params.acl_filters[i - 1]); | acls = &(auth->params.acl_filters[i - 1]); |
| } else if (strcmp(attr, "MPD_LIMIT") == 0) { | } else if (strcmp(attr, "MPD_LIMIT") == 0) { |
| acl1 = val; | acl1 = val; |
| acl2 = strsep(&acl1, "#"); | acl2 = strsep(&acl1, "#"); |
| if (strcasecmp(acl2, "in") == 0) { | if (strcasecmp(acl2, "in") == 0) { |
| i = 0; | i = 0; |
| } else if (strcasecmp(acl2, "out") == 0) { | } else if (strcasecmp(acl2, "out") == 0) { |
| i = 1; | i = 1; |
| } else { | } else { |
| Log(LG_ERR, ("[%s] Ext-auth: wrong limit direction: '%s'", | Log(LG_ERR, ("[%s] Ext-auth: wrong limit direction: '%s'", |
| auth->info.lnkname, acl2)); | auth->info.lnkname, acl2)); |
| continue; | continue; |
| } | } |
| acls = &(auth->params.acl_limits[i]); | acls = &(auth->params.acl_limits[i]); |
| } else { | } else { |
| Log(LG_ERR, ("[%s] Ext-auth: Dropping MPD vendor specific attribute: '%s'", | Log(LG_ERR, ("[%s] Ext-auth: Dropping MPD vendor specific attribute: '%s'", |
| auth->info.lnkname, attr)); | auth->info.lnkname, attr)); |
| continue; | continue; |
| } | } |
| #endif /* USE_NG_BPF */ | #endif /* USE_NG_BPF */ |
| |
|
| if (acl1 == NULL) { | if (acl1 == NULL) { |
| Log(LG_ERR, ("[%s] Ext-auth: incorrect acl!", | Log(LG_ERR, ("[%s] Ext-auth: incorrect acl!", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| continue; | continue; |
| } | } |
| | acl3 = acl1; |
| acl3 = acl1; | strsep(&acl3, "="); |
| strsep(&acl3, "="); | acl2 = acl1; |
| acl2 = acl1; | strsep(&acl2, "#"); |
| strsep(&acl2, "#"); | i = atol(acl1); |
| i = atol(acl1); | if (i <= 0) { |
| if (i <= 0) { | Log(LG_ERR, ("[%s] Ext-auth: wrong acl number: %i", |
| Log(LG_ERR, ("[%s] Ext-auth: wrong acl number: %i", | auth->info.lnkname, i)); |
| auth->info.lnkname, i)); | continue; |
| continue; | } |
| } | if ((acl3 == NULL) || (acl3[0] == 0)) { |
| if ((acl3 == NULL) || (acl3[0] == 0)) { | Log(LG_ERR, ("[%s] Ext-auth: wrong acl", auth->info.lnkname)); |
| Log(LG_ERR, ("[%s] Ext-auth: wrong acl", auth->info.lnkname)); | continue; |
| continue; | } |
| } | acls1 = Malloc(MB_AUTH, sizeof(struct acl) + strlen(acl3)); |
| acls1 = Malloc(MB_AUTH, sizeof(struct acl) + strlen(acl3)); | if (strcmp(attr, "MPD_TABLE_STATIC") != 0) { |
| if (strcmp(attr, "MPD_TABLE_STATIC") != 0) { | acls1->number = i; |
| acls1->number = i; | acls1->real_number = 0; |
| acls1->real_number = 0; | } else { |
| } else { | acls1->number = 0; |
| acls1->number = 0; | acls1->real_number = i; |
| acls1->real_number = i; | } |
| } | if (acl2) |
| if (acl2) | strlcpy(acls1->name, acl2, sizeof(acls1->name)); |
| strlcpy(acls1->name, acl2, sizeof(acls1->name)); | strcpy(acls1->rule, acl3); |
| strcpy(acls1->rule, acl3); | while ((*acls != NULL) && ((*acls)->number < acls1->number)) |
| while ((*acls != NULL) && ((*acls)->number < acls1->number)) | acls = &((*acls)->next); |
| acls = &((*acls)->next); | |
| |
|
| if (*acls == NULL) { | if (*acls == NULL) { |
| acls1->next = NULL; | acls1->next = NULL; |
| } else if (((*acls)->number == acls1->number) && | } else if (((*acls)->number == acls1->number) && |
| (strcmp(attr, "MPD_TABLE") != 0) && | (strcmp(attr, "MPD_TABLE") != 0) && |
| (strcmp(attr, "MPD_TABLE_STATIC") != 0)) { | (strcmp(attr, "MPD_TABLE_STATIC") != 0)) { |
| Log(LG_ERR, ("[%s] Ext-auth: duplicate acl", | Log(LG_ERR, ("[%s] Ext-auth: duplicate acl", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| continue; | continue; |
| } else { | } else { |
| acls1->next = *acls; | acls1->next = *acls; |
| } | } |
| *acls = acls1; | *acls = acls1; |
| #endif /* USE_IPFW or USE_NG_BPF */ | #endif /* USE_IPFW or USE_NG_BPF */ |
| |
|
| } else { | } else { |
| Log(LG_ERR, ("[%s] Ext-auth: Unknown attr:'%s'", | Log(LG_ERR, ("[%s] Ext-auth: Unknown attr:'%s'", |
| auth->info.lnkname, attr)); | auth->info.lnkname, attr)); |
| } | } |
| } | } |
| | |
| pclose(fp); | pclose(fp); |
| return (0); | return (0); |
| } |
} |
| |
|
| /* |
/* |
| * AuthExternalAcct() |
* AuthExternalAcct() |
| * | * |
| * Accounting via call external script extacct-script |
* Accounting via call external script extacct-script |
| */ |
*/ |
| | |
| static int |
static int |
| AuthExternalAcct(AuthData auth) |
AuthExternalAcct(AuthData auth) |
| { |
{ |
| char line[256]; | char line[256]; |
| FILE *fp; | FILE *fp; |
| char *attr, *val; | char *attr, *val; |
| int len; | int len; |
| | |
| if (!auth->conf.extacct_script || !auth->conf.extacct_script[0]) { | if (!auth->conf.extacct_script || !auth->conf.extacct_script[0]) { |
| Log(LG_ERR, ("[%s] Ext-acct: Script not specified!", | Log(LG_ERR, ("[%s] Ext-acct: Script not specified!", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| return (-1); | return (-1); |
| } | } |
| if (strchr(auth->params.authname, '\'') || | if (strchr(auth->params.authname, '\'') || |
| strchr(auth->params.authname, '\n')) { |
strchr(auth->params.authname, '\n')) { |
| Log(LG_ERR, ("[%s] Ext-acct: Denied character in USER_NAME!", | Log(LG_ERR, ("[%s] Ext-acct: Denied character in USER_NAME!", |
| auth->info.lnkname)); | auth->info.lnkname)); |
| return (-1); | return (-1); |
| } | } |
| snprintf(line, sizeof(line), "%s '%s'", | snprintf(line, sizeof(line), "%s '%s'", |
| auth->conf.extacct_script, auth->params.authname); | auth->conf.extacct_script, auth->params.authname); |
| Log(LG_AUTH, ("[%s] Ext-acct: Invoking acct program: '%s'", | Log(LG_AUTH, ("[%s] Ext-acct: Invoking acct program: '%s'", |
| auth->info.lnkname, line)); | auth->info.lnkname, line)); |
| if ((fp = popen(line, "r+")) == NULL) { | if ((fp = popen(line, "r+")) == NULL) { |
| Perror("Popen"); | Perror("Popen"); |
| return (-1); | return (-1); |
| } | } |
| | /* SENDING REQUEST */ |
| | fprintf(fp, "ACCT_STATUS_TYPE:%s\n", |
| | (auth->acct_type == AUTH_ACCT_START) ? |
| | "START" : ((auth->acct_type == AUTH_ACCT_STOP) ? |
| | "STOP" : "UPDATE")); |
| |
|
| /* SENDING REQUEST */ | fprintf(fp, "ACCT_SESSION_ID:%s\n", auth->info.session_id); |
| fprintf(fp, "ACCT_STATUS_TYPE:%s\n", | fprintf(fp, "ACCT_MULTI_SESSION_ID:%s\n", auth->info.msession_id); |
| (auth->acct_type == AUTH_ACCT_START)? | fprintf(fp, "USER_NAME:%s\n", auth->params.authname); |
| "START":((auth->acct_type == AUTH_ACCT_STOP)? | fprintf(fp, "IFACE:%s\n", auth->info.ifname); |
| "STOP":"UPDATE")); | fprintf(fp, "IFACE_INDEX:%d\n", auth->info.ifindex); |
| | fprintf(fp, "BUNDLE:%s\n", auth->info.bundname); |
| | fprintf(fp, "LINK:%s\n", auth->info.lnkname); |
| | fprintf(fp, "NAS_PORT:%d\n", auth->info.linkID); |
| | fprintf(fp, "NAS_PORT_TYPE:%s\n", auth->info.phys_type->name); |
| | fprintf(fp, "ACCT_LINK_COUNT:%d\n", auth->info.n_links); |
| | fprintf(fp, "CALLING_STATION_ID:%s\n", auth->params.callingnum); |
| | fprintf(fp, "CALLED_STATION_ID:%s\n", auth->params.callednum); |
| | fprintf(fp, "SELF_NAME:%s\n", auth->params.selfname); |
| | fprintf(fp, "PEER_NAME:%s\n", auth->params.peername); |
| | fprintf(fp, "SELF_ADDR:%s\n", auth->params.selfaddr); |
| | fprintf(fp, "PEER_ADDR:%s\n", auth->params.peeraddr); |
| | fprintf(fp, "PEER_PORT:%s\n", auth->params.peerport); |
| | fprintf(fp, "PEER_MAC_ADDR:%s\n", auth->params.peermacaddr); |
| | fprintf(fp, "PEER_IFACE:%s\n", auth->params.peeriface); |
| | fprintf(fp, "PEER_IDENT:%s\n", auth->info.peer_ident); |
| |
|
| fprintf(fp, "ACCT_SESSION_ID:%s\n", auth->info.session_id); | fprintf(fp, "FRAMED_IP_ADDRESS:%s\n", |
| fprintf(fp, "ACCT_MULTI_SESSION_ID:%s\n", auth->info.msession_id); | inet_ntoa(auth->info.peer_addr)); |
| fprintf(fp, "USER_NAME:%s\n", auth->params.authname); | |
| fprintf(fp, "IFACE:%s\n", auth->info.ifname); | |
| fprintf(fp, "IFACE_INDEX:%d\n", auth->info.ifindex); | |
| fprintf(fp, "BUNDLE:%s\n", auth->info.bundname); | |
| fprintf(fp, "LINK:%s\n", auth->info.lnkname); | |
| fprintf(fp, "NAS_PORT:%d\n", auth->info.linkID); | |
| fprintf(fp, "NAS_PORT_TYPE:%s\n", auth->info.phys_type->name); | |
| fprintf(fp, "ACCT_LINK_COUNT:%d\n", auth->info.n_links); | |
| fprintf(fp, "CALLING_STATION_ID:%s\n", auth->params.callingnum); | |
| fprintf(fp, "CALLED_STATION_ID:%s\n", auth->params.callednum); | |
| fprintf(fp, "SELF_NAME:%s\n", auth->params.selfname); | |
| fprintf(fp, "PEER_NAME:%s\n", auth->params.peername); | |
| fprintf(fp, "SELF_ADDR:%s\n", auth->params.selfaddr); | |
| fprintf(fp, "PEER_ADDR:%s\n", auth->params.peeraddr); | |
| fprintf(fp, "PEER_PORT:%s\n", auth->params.peerport); | |
| fprintf(fp, "PEER_MAC_ADDR:%s\n", auth->params.peermacaddr); | |
| fprintf(fp, "PEER_IFACE:%s\n", auth->params.peeriface); | |
| fprintf(fp, "PEER_IDENT:%s\n", auth->info.peer_ident); | |
| |
|
| fprintf(fp, "FRAMED_IP_ADDRESS:%s\n", | if (auth->acct_type == AUTH_ACCT_STOP) |
| inet_ntoa(auth->info.peer_addr)); | fprintf(fp, "ACCT_TERMINATE_CAUSE:%s\n", auth->info.downReason); |
| |
|
| if (auth->acct_type == AUTH_ACCT_STOP) | if (auth->acct_type != AUTH_ACCT_START) { |
| fprintf(fp, "ACCT_TERMINATE_CAUSE:%s\n", auth->info.downReason); | |
| |
| if (auth->acct_type != AUTH_ACCT_START) { | |
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| struct svcstatrec *ssr; | struct svcstatrec *ssr; |
| | |
| #endif |
#endif |
| fprintf(fp, "ACCT_SESSION_TIME:%ld\n", | fprintf(fp, "ACCT_SESSION_TIME:%ld\n", |
| (long int)(time(NULL) - auth->info.last_up)); | (long int)(time(NULL) - auth->info.last_up)); |
| fprintf(fp, "ACCT_INPUT_OCTETS:%llu\n", | fprintf(fp, "ACCT_INPUT_OCTETS:%llu\n", |
| (long long unsigned)auth->info.stats.recvOctets); | (long long unsigned)auth->info.stats.recvOctets); |
| fprintf(fp, "ACCT_INPUT_PACKETS:%llu\n", | fprintf(fp, "ACCT_INPUT_PACKETS:%llu\n", |
| (long long unsigned)auth->info.stats.recvFrames); | (long long unsigned)auth->info.stats.recvFrames); |
| fprintf(fp, "ACCT_OUTPUT_OCTETS:%llu\n", | fprintf(fp, "ACCT_OUTPUT_OCTETS:%llu\n", |
| (long long unsigned)auth->info.stats.xmitOctets); | (long long unsigned)auth->info.stats.xmitOctets); |
| fprintf(fp, "ACCT_OUTPUT_PACKETS:%llu\n", | fprintf(fp, "ACCT_OUTPUT_PACKETS:%llu\n", |
| (long long unsigned)auth->info.stats.xmitFrames); | (long long unsigned)auth->info.stats.xmitFrames); |
| #ifdef USE_NG_BPF |
#ifdef USE_NG_BPF |
| SLIST_FOREACH(ssr, &auth->info.ss.stat[0], next) { | SLIST_FOREACH(ssr, &auth->info.ss.stat[0], next) { |
| fprintf(fp, "MPD_INPUT_OCTETS:%s:%llu\n", | fprintf(fp, "MPD_INPUT_OCTETS:%s:%llu\n", |
| ssr->name, (long long unsigned)ssr->Octets); | ssr->name, (long long unsigned)ssr->Octets); |
| fprintf(fp, "MPD_INPUT_PACKETS:%s:%llu\n", | fprintf(fp, "MPD_INPUT_PACKETS:%s:%llu\n", |
| ssr->name, (long long unsigned)ssr->Packets); | ssr->name, (long long unsigned)ssr->Packets); |
| | } |
| | SLIST_FOREACH(ssr, &auth->info.ss.stat[1], next) { |
| | fprintf(fp, "MPD_OUTPUT_OCTETS:%s:%llu\n", |
| | ssr->name, (long long unsigned)ssr->Octets); |
| | fprintf(fp, "MPD_OUTPUT_PACKETS:%s:%llu\n", |
| | ssr->name, (long long unsigned)ssr->Packets); |
| | } |
| | #endif /* USE_NG_BPF */ |
| } |
} |
| SLIST_FOREACH(ssr, &auth->info.ss.stat[1], next) { | /* REQUEST DONE */ |
| fprintf(fp, "MPD_OUTPUT_OCTETS:%s:%llu\n", | fprintf(fp, "\n"); |
| ssr->name, (long long unsigned)ssr->Octets); | |
| fprintf(fp, "MPD_OUTPUT_PACKETS:%s:%llu\n", | |
| ssr->name, (long long unsigned)ssr->Packets); | |
| } | |
| #endif /* USE_NG_BPF */ | |
| } | |
| |
|
| /* REQUEST DONE */ | /* REPLY PROCESSING */ |
| fprintf(fp, "\n"); | while (fgets(line, sizeof(line), fp)) { |
| | /* trim trailing newline */ |
| | len = strlen(line); |
| | if (len > 0 && line[len - 1] == '\n') { |
| | line[len - 1] = '\0'; |
| | len--; |
| | } |
| | /* Empty line is the end marker */ |
| | if (len == 0) |
| | break; |
| |
|
| /* REPLY PROCESSING */ | /* split line on attr:value */ |
| while (fgets(line, sizeof(line), fp)) { | val = line; |
| /* trim trailing newline */ | attr = strsep(&val, ":"); |
| len = strlen(line); | |
| if (len > 0 && line[len - 1] == '\n') { | |
| line[len - 1] = '\0'; | |
| len--; | |
| } | |
| |
|
| /* Empty line is the end marker */ | Log(LG_AUTH2, ("[%s] Ext-acct: attr:'%s', value:'%s'", |
| if (len == 0) | auth->info.lnkname, attr, val)); |
| break; | |
| |
|
| /* split line on attr:value */ | if (strcmp(attr, "MPD_DROP_USER") == 0) { |
| val = line; | auth->drop_user = atoi(val); |
| attr = strsep(&val, ":"); | |
| |
|
| Log(LG_AUTH2, ("[%s] Ext-acct: attr:'%s', value:'%s'", | } else { |
| auth->info.lnkname, attr, val)); | Log(LG_ERR, ("[%s] Ext-acct: Unknown attr:'%s'", |
| | auth->info.lnkname, attr)); |
| if (strcmp(attr, "MPD_DROP_USER") == 0) { | } |
| auth->drop_user = atoi(val); | |
| |
| } else { | |
| Log(LG_ERR, ("[%s] Ext-acct: Unknown attr:'%s'", | |
| auth->info.lnkname, attr)); | |
| } |
} |
| } | |
| | pclose(fp); |
| pclose(fp); | return (0); |
| return (0); | |
| } |
} |