Index: configure.in =================================================================== RCS file: /home/cvs/gateway/configure.in,v retrieving revision 1.186 diff -u -b -w -r1.186 configure.in --- configure.in 4 May 2009 21:35:52 -0000 1.186 +++ configure.in 10 Jun 2009 10:32:41 -0000 @@ -665,26 +665,6 @@ ]) -dnl Implement the --enable-pam option. - -AC_ARG_ENABLE(pam, -[ --enable-pam enable PAM authentication @<:@disabled@:>@], [ - if test "$enableval" = "yes" - then - AC_CHECK_LIB(pam, pam_end) - AC_CHECK_LIB(dl,main) - AC_CHECK_HEADERS(security/pam_appl.h) - PAMTARGET="pam" - else - PAMTARGET="no-pam" - fi -]) -case "$PAMTARGET" in -no-pam) echo PAM authentication is disabled. ;; -pam) echo PAM authentication is enabled. ;; -esac - - dnl Implement --enable-debug option. AC_ARG_ENABLE(debug, @@ -785,6 +765,31 @@ ]) +dnl Implement the --enable-pam option. + +AC_CONFIG_SECTION([Configuring PAM support]) + +AC_MSG_CHECKING([whether to compile with PAM support]) +AC_ARG_ENABLE(pam, +[ --enable-pam enable PAM authentication @<:@disabled@:>@], [ + if test "$enableval" = "yes" + then + AC_CHECK_LIB(pam, pam_end) + AC_CHECK_LIB(dl,main) + AC_CHECK_HEADER([security/pam_appl.h], + AC_DEFINE(HAVE_PAM_SECURITY) \ + AC_DEFINE(HAVE_PAM) \ + AC_MSG_RESULT([enabling PAM for authentication]), + [AC_CHECK_HEADER([pam/pam_appl.h], + AC_DEFINE(HAVE_PAM_PAM) \ + AC_DEFINE(HAVE_PAM) \ + AC_MSG_RESULT([enabling PAM for authentication]) + )] + ) + fi +]) + + dnl Implement the --with-ssl option. AC_CONFIG_SECTION([Configuring OpenSSL support]) Index: gw-config.h.in =================================================================== RCS file: /home/cvs/gateway/gw-config.h.in,v retrieving revision 1.23 diff -u -b -w -r1.23 gw-config.h.in --- gw-config.h.in 4 May 2009 21:35:53 -0000 1.23 +++ gw-config.h.in 10 Jun 2009 10:32:41 -0000 @@ -187,8 +187,12 @@ /* Define if there is a socklen_t in */ #undef HAVE_SOCKLEN_T -/* Define if the PAM headers are on the local machine */ -#undef HAVE_SECURITY_PAM_APPL_H +/* Define if you have the pam headers */ +#undef HAVE_PAM + +/* Define where are the PAM headers */ +#undef HAVE_PAM_SECURITY +#undef HAVE_PAM_PAM /* Define if you want to turn off assertion checking */ #undef NO_GWASSERT Index: gw/smsbox.c =================================================================== RCS file: /home/cvs/gateway/gw/smsbox.c,v retrieving revision 1.283 diff -u -b -w -r1.283 smsbox.c --- gw/smsbox.c 20 May 2009 10:12:46 -0000 1.283 +++ gw/smsbox.c 10 Jun 2009 10:32:44 -0000 @@ -79,8 +79,10 @@ #include "ota_compiler.h" #include "xml_shared.h" -#ifdef HAVE_SECURITY_PAM_APPL_H +#ifdef HAVE_PAM_SECURITY #include +#elif defined HAVE_PAM_PAM +#include #endif @@ -1851,7 +1853,7 @@ */ -#ifdef HAVE_SECURITY_PAM_APPL_H /*Module for pam authentication */ +#ifdef HAVE_PAM /* Module for pam authentication */ /* * Use PAM (Pluggable Authentication Module) to check sendsms authentication. @@ -1914,7 +1916,7 @@ }; -static int authenticate(const char *login, const char *passwd) +static int authenticate(const char *acl, const char *login, const char *passwd) { pam_handle_t *pamh; int pam_error; @@ -1922,9 +1924,11 @@ PAM_username = login; PAM_password = passwd; - pam_error = pam_start("kannel", login, &PAM_conversation, &pamh); + pam_error = pam_start(acl, login, &PAM_conversation, &pamh); + info(0, "Starting PAM for user: %s", login); if (pam_error != PAM_SUCCESS || (pam_error = pam_authenticate(pamh, 0)) != PAM_SUCCESS) { + warning(0, "PAM auth failed for user: %s", login); pam_end(pamh, pam_error); return 0; } @@ -1933,36 +1937,7 @@ return 1; } - -/* - * Check for matching username and password for requests. - * Return an URLTranslation if successful NULL otherwise. - */ - -static int pam_authorise_user(List *list) -{ - Octstr *val, *user = NULL; - char *pwd, *login; - int result; - - if ((user = http_cgi_variable(list, "user")) == NULL && - (user = http_cgi_variable(list, "username"))==NULL) - return 0; - login = octstr_get_cstr(user); - - if ((val = http_cgi_variable(list, "password")) == NULL && - (val = http_cgi_variable(list, "pass")) == NULL) - return 0; - - pwd = octstr_get_cstr(val); - result = authenticate(login, pwd); - - return result; -} - -#endif /* HAVE_SECURITY_PAM_APPL_H */ - - +#endif /* HAVE_PAM */ static Octstr* store_uuid(Msg *msg) @@ -2340,7 +2315,6 @@ } while ((receiv = gwlist_extract_first(allowed)) != NULL) { - O_DESTROY(msg->sms.receiver); msg->sms.receiver = octstr_duplicate(receiv); @@ -2441,9 +2415,9 @@ if ((t = urltrans_find_username(translations, username))==NULL) return NULL; - if (octstr_compare(password, urltrans_password(t))!=0) + if (octstr_compare(password, urltrans_password(t))!=0) { return NULL; - else { + } else { Octstr *allow_ip = urltrans_allow_ip(t); Octstr *deny_ip = urltrans_deny_ip(t); @@ -2479,20 +2453,52 @@ static URLTranslation *authorise_user(List *list, Octstr *client_ip) { -#ifdef HAVE_SECURITY_PAM_APPL_H URLTranslation *t; - t = urltrans_find_username(translations, octstr_imm("pam")); + /* We first try to authorize locally, because is faster and more likely to be used */ + t = default_authorise_user(list, client_ip); if (t != NULL) { - if (pam_authorise_user(list)) return t; - else + } +#if HAVE_PAM + int i; + Octstr *allow_ip, *deny_ip; + + Octstr *val, *user = NULL; + char *pwd, *login, *acl; + int result; + + List *trans = urltrans_find_type(translations, TRANSTYPE_SENDSMS_PAM); + for (i = 0; i < gwlist_len(trans); ++i) { + t = gwlist_get(trans, i); + if (t != NULL) { + if ((user = http_cgi_variable(list, "user")) == NULL && + (user = http_cgi_variable(list, "username"))==NULL) + return NULL; + login = octstr_get_cstr(user); + + if ((val = http_cgi_variable(list, "password")) == NULL && + (val = http_cgi_variable(list, "pass")) == NULL) + return NULL; + + pwd = octstr_get_cstr(val); + acl = octstr_get_cstr(urltrans_username(t)); + result = authenticate(acl, login, pwd); + if (result) { + urltrans_set_username(t, octstr_format("%S:%S", urltrans_username(t), user)); + allow_ip = urltrans_allow_ip(t); + deny_ip = urltrans_deny_ip(t); + if (is_allowed_ip(allow_ip, deny_ip, client_ip) == 0) { + warning(0, "[pam] Non-allowed connect tried by <%s> from <%s>, ignored", + octstr_get_cstr(urltrans_username(t)), octstr_get_cstr(client_ip)); + return NULL; + } + return t; + } + } + } +#endif /* HAVE_PAM */ return NULL; - } else - return default_authorise_user(list, client_ip); -#else - return default_authorise_user(list, client_ip); -#endif } @@ -2710,13 +2716,13 @@ ret = octstr_create("Unsupported content-type, rejected"); } - if (ret == NULL) + if (ret == NULL) { ret = smsbox_req_handle(t, client_ip, client, from, to, body, charset, udh, smsc, mclass, mwi, coding, compress, validity, deferred, status, dlr_mask, dlr_url, account, pid, alt_dcs, rpi, tolist, binfo, priority, meta_data); - + } } error2: octstr_destroy(user); Index: gw/urltrans.c =================================================================== RCS file: /home/cvs/gateway/gw/urltrans.c,v retrieving revision 1.111 diff -u -b -w -r1.111 urltrans.c --- gw/urltrans.c 14 Jan 2009 11:11:46 -0000 1.111 +++ gw/urltrans.c 10 Jun 2009 10:32:45 -0000 @@ -205,7 +205,7 @@ if (ot == NULL) return -1; - if (ot->type != TRANSTYPE_SENDSMS && ot->keyword_regex == NULL) + if (ot->type != TRANSTYPE_SENDSMS && ot->type != TRANSTYPE_SENDSMS_PAM && ot->keyword_regex == NULL) gwlist_append(trans->defaults, ot); else gwlist_append(trans->list, ot); @@ -244,6 +244,15 @@ } gwlist_destroy(list, NULL); + list = cfg_get_multi_group(cfg, octstr_imm("sendsms-pam-user")); + while (list && (grp = gwlist_extract_first(list)) != NULL) { + if (urltrans_add_one(trans, grp) == -1) { + gwlist_destroy(list, NULL); + return -1; + } + } + gwlist_destroy(list, NULL); + return 0; } @@ -276,7 +285,6 @@ } - URLTranslation *urltrans_find_username(URLTranslationList *trans, Octstr *name) { URLTranslation *t; @@ -293,6 +301,27 @@ return NULL; } + +/* + * Returns a list with all the translations of a given type + */ +List *urltrans_find_type(URLTranslationList *trans, int type) +{ + URLTranslation *t; + List *tlist; + int i; + + tlist = gwlist_create(); + + for (i = 0; i < gwlist_len(trans->list); ++i) { + t = gwlist_get(trans->list, i); + if (t->type == type) { + gwlist_append(tlist, t); + } + } + return tlist; +} + /* * Remove the first word and the whitespace that follows it from * the start of the message data. @@ -662,7 +691,8 @@ { Octstr *result, *pattern; - if (request->sms.sms_type != report_mo && t->type == TRANSTYPE_SENDSMS) + if (request->sms.sms_type != report_mo && + (t->type == TRANSTYPE_SENDSMS || t->type == TRANSTYPE_SENDSMS_PAM)) return octstr_create(""); /* check if this is a delivery report message or not */ @@ -757,6 +787,11 @@ return t->footer; } +void urltrans_set_username(URLTranslation *t, Octstr *value) +{ + t->username = value; +} + Octstr *urltrans_name(URLTranslation *t) { return t->name; @@ -868,7 +903,7 @@ Octstr *url, *post_url, *post_xml, *text, *file, *exec; Octstr *accepted_smsc, *accepted_account, *forced_smsc, *default_smsc; Octstr *grpname; - int is_sms_service; + int is_sms_service, is_pam; Octstr *accepted_smsc_regex; Octstr *accepted_account_regex; Octstr *allowed_prefix_regex; @@ -884,11 +919,15 @@ if (grpname == NULL) return NULL; - if (octstr_str_compare(grpname, "sms-service") == 0) + is_pam = 0; + if (octstr_str_compare(grpname, "sms-service") == 0) { is_sms_service = 1; - else if (octstr_str_compare(grpname, "sendsms-user") == 0) + } else if (octstr_str_compare(grpname, "sendsms-user") == 0) { + is_sms_service = 0; + } else if (octstr_str_compare(grpname, "sendsms-pam-user") == 0) { is_sms_service = 0; - else { + is_pam = 1; + } else { octstr_destroy(grpname); return NULL; } @@ -989,7 +1028,6 @@ } gwlist_destroy(l, octstr_destroy_item); } - octstr_append_cstr(keyword_regex, ")[ ]*"); } @@ -1048,7 +1086,8 @@ ot->denied_recv_prefix = cfg_get(grp, octstr_imm("denied-receiver-prefix")); denied_receiver_prefix_regex = cfg_get(grp, octstr_imm("denied-receiver-prefix-regex")); if (denied_receiver_prefix_regex != NULL) { - if ((ot->denied_receiver_prefix_regex = gw_regex_comp(denied_receiver_prefix_regex, REG_EXTENDED)) == NULL) + if ((ot->denied_receiver_prefix_regex = gw_regex_comp(denied_receiver_prefix_regex, + REG_EXTENDED)) == NULL) panic(0, "Could not compile pattern '%s'",octstr_get_cstr(denied_receiver_prefix_regex)); octstr_destroy(denied_receiver_prefix_regex); } @@ -1058,18 +1097,24 @@ ot->has_catchall_arg = (count_occurences(ot->pattern, octstr_imm("%r")) > 0) || (count_occurences(ot->pattern, octstr_imm("%a")) > 0); - } else { + if (is_pam) + ot->type = TRANSTYPE_SENDSMS_PAM; + else ot->type = TRANSTYPE_SENDSMS; ot->pattern = octstr_create(""); ot->args = 0; ot->has_catchall_arg = 0; ot->catch_all = 1; + if (!is_pam) { ot->username = cfg_get(grp, octstr_imm("username")); ot->password = cfg_get(grp, octstr_imm("password")); + } else { + ot->username = cfg_get(grp, octstr_imm("acl")); + } ot->dlr_url = cfg_get(grp, octstr_imm("dlr-url")); grp_dump(grp); - if (ot->password == NULL) { + if (!is_pam && ot->password == NULL) { error(0, "Password required for send-sms user"); goto error; } @@ -1086,9 +1131,9 @@ } ot->forced_smsc = forced_smsc; octstr_destroy(default_smsc); - } else if (default_smsc != NULL) + } else if (default_smsc != NULL) { ot->default_smsc = default_smsc; - + } ot->deny_ip = cfg_get(grp, octstr_imm("user-deny-ip")); ot->allow_ip = cfg_get(grp, octstr_imm("user-allow-ip")); ot->default_sender = cfg_get(grp, octstr_imm("default-sender")); Index: gw/urltrans.h =================================================================== RCS file: /home/cvs/gateway/gw/urltrans.h,v retrieving revision 1.38 diff -u -b -w -r1.38 urltrans.h --- gw/urltrans.h 12 Jan 2009 16:46:56 -0000 1.38 +++ gw/urltrans.h 10 Jun 2009 10:32:45 -0000 @@ -106,7 +106,8 @@ TRANSTYPE_TEXT, TRANSTYPE_FILE, TRANSTYPE_EXECUTE, - TRANSTYPE_SENDSMS + TRANSTYPE_SENDSMS, + TRANSTYPE_SENDSMS_PAM }; @@ -182,6 +183,12 @@ /* + * find matching URLTranslation for the given type, or NULL + * if not found. + */ +List *urltrans_find_type(URLTranslationList *trans, + int type); +/* * find matching URLTranslation for the given 'username', or NULL * if not found. Password must be checked afterwards */ @@ -285,10 +292,11 @@ */ Octstr *urltrans_footer(URLTranslation *t); +void urltrans_set_username(URLTranslation *t, Octstr *value); /* * return the name, username or password string, or NULL if not set - * (used only with TRANSTYPE_SENDSMS) + * (used only with TRANSTYPE_SENDSMS and TRANSTYPE_SENDSMS_PAM) */ Octstr *urltrans_name(URLTranslation *t); Octstr *urltrans_username(URLTranslation *t); Index: gwlib/cfg.def =================================================================== RCS file: /home/cvs/gateway/gwlib/cfg.def,v retrieving revision 1.140 diff -u -b -w -r1.140 cfg.def --- gwlib/cfg.def 9 Jun 2009 17:05:08 -0000 1.140 +++ gwlib/cfg.def 10 Jun 2009 10:32:46 -0000 @@ -489,6 +489,34 @@ ) +MULTI_GROUP(sendsms-pam-user, + OCTSTR(name) + OCTSTR(acl) + OCTSTR(user-deny-ip) + OCTSTR(user-allow-ip) + OCTSTR(forced-smsc) + OCTSTR(default-smsc) + OCTSTR(faked-sender) + OCTSTR(default-sender) + OCTSTR(max-messages) + OCTSTR(concatenation) + OCTSTR(split-chars) + OCTSTR(split-suffix) + OCTSTR(omit-empty) + OCTSTR(header) + OCTSTR(footer) + OCTSTR(allowed-prefix) + OCTSTR(denied-prefix) + OCTSTR(white-list) + OCTSTR(black-list) + OCTSTR(dlr-url) + OCTSTR(allowed-prefix-regex) + OCTSTR(denied-prefix-regex) + OCTSTR(white-list-regex) + OCTSTR(black-list-regex) +) + + MULTI_GROUP(ota-setting, OCTSTR(ota-id) OCTSTR(location)