version 1.1.1.2, 2013/07/22 08:44:29
|
version 1.1.1.4.2.1, 2023/09/27 11:08:00
|
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; | #ifdef USE_RADIUS |
ap->msdomain = NULL; | ap->eapmsg = NULL; |
| ap->state = NULL; |
| ap->class = NULL; |
| ap->filter_id = NULL; |
| #endif |
| 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); |
|
|
|
|
#ifdef USE_RADIUS |
|
Freee(ap->eapmsg); |
|
Freee(ap->state); |
|
Freee(ap->class); |
|
Freee(ap->filter_id); |
|
#endif |
|
|
#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); | |
|
|
|
#ifdef USE_RADIUS |
|
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); |
|
#endif |
|
|
#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 308 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); |
| |
| #ifdef USE_RADIUS |
| EapInit(l); |
| RadiusInit(l); |
| #endif |
} |
} |
|
|
/* |
/* |
Line 300 AuthInit(Link l)
|
Line 329 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 343 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 362 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; |
| #ifdef USE_RADIUS |
| case PROTO_EAP: |
| EapStart(l, AUTH_SELF_TO_PEER); |
| break; |
| #endif |
| 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; |
| #ifdef USE_RADIUS |
| case PROTO_EAP: |
| EapStart(l, AUTH_PEER_TO_SELF); |
| break; |
| #endif |
| default: |
| assert(0); |
| } |
} |
} |
|
|
/* |
/* |
* AuthInput() |
* AuthInput() |
* |
* |
* Deal with PAP/CHAP/EAP packet |
* Deal with PAP/CHAP/EAP packet |
|
* But cannot be called for EAP packet if RADIUS support is not compiled in. |
*/ |
*/ |
|
|
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); | #ifdef USE_RADIUS |
| 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 |
| #endif |
| 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); | #ifdef USE_RADIUS |
break; | case PROTO_EAP: |
case PROTO_CHAP: | EapInput(l, auth, pkt, len); |
ChapInput(l, auth, pkt, len); | break; |
break; | #endif |
case PROTO_EAP: | default: |
EapInput(l, auth, pkt, len); | assert(0); |
break; | } |
default: | |
assert(0); | mbfree(bp); |
} | |
| |
mbfree(bp); | |
} |
} |
|
|
/* |
/* |
Line 506 AuthInput(Link l, int proto, Mbuf bp)
|
Line 551 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 */ | #ifdef USE_RADIUS |
NgFuncWritePppFrameLink(l, proto, bp); | if (proto == PROTO_EAP) { |
| 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 |
| #endif |
| 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 601 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 630 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 708 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 730 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); | #ifdef USE_RADIUS |
paction_cancel(&a->thread); | EapStop(&a->eap); |
| #endif |
| paction_cancel(&a->thread); |
} |
} |
|
|
/* |
/* |
Line 697 AuthStop(Link l)
|
Line 746 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 971 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 989 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)) | #ifdef USE_RADIUS |
err |= RadiusAccount(auth); | if (Enabled(&auth->conf.options, AUTH_CONF_RADIUS_ACCT)) |
| err |= RadiusAccount(auth); |
| #endif |
#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) { | #ifdef USE_RADIUS |
AuthDataDestroy(auth); | /* Cleanup */ |
return; | RadiusClose(auth); |
} | #endif |
| |
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 1072 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 1128 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 1189 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; |
| } |
| } |
| #ifdef USE_RADIUS |
| 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; |
|
} |
} |
} |
} | #endif |
| |
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 */ | #ifdef USE_RADIUS |
RadiusClose(auth); | /* cleanup */ |
| RadiusClose(auth); |
if (was_canceled) { | #endif |
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 1458 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 1470 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 1479 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 1662 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 1730 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 1773 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 1938 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 1974 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: | #ifdef USE_RADIUS |
return EapCode(code, buf, len); | case PROTO_EAP: |
| return EapCode(code, buf, len); |
|
|
case PROTO_CHAP: | #endif |
return ChapCode(code, buf, len); | case PROTO_CHAP: |
| 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 1998 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); | |
} |
} |