diff --git a/apps/announce_auth/AnnounceAuth.cpp b/apps/announce_auth/AnnounceAuth.cpp index 2ae0ec9b..7f271d92 100644 --- a/apps/announce_auth/AnnounceAuth.cpp +++ b/apps/announce_auth/AnnounceAuth.cpp @@ -33,7 +33,7 @@ #include "sems.h" #include "log.h" -#include "../../core/plug-in/uac_auth/UACAuth.h" +#include "ampi/UACAuthAPI.h" #include "AmUAC.h" #include "AmPlugIn.h" @@ -128,11 +128,15 @@ AnnounceAuthDialog::AnnounceAuthDialog(const string& filename, const string& auth_user, const string& auth_pwd) : filename(filename), - CredentialHolder(auth_realm, auth_user, auth_pwd) + credentials(auth_realm, auth_user, auth_pwd) { } +UACAuthCred* AnnounceAuthDialog::getCredentials() { + return &credentials; +} + AnnounceAuthDialog::~AnnounceAuthDialog() { } diff --git a/apps/announce_auth/AnnounceAuth.h b/apps/announce_auth/AnnounceAuth.h index 3f33e9ae..a79b0ce3 100644 --- a/apps/announce_auth/AnnounceAuth.h +++ b/apps/announce_auth/AnnounceAuth.h @@ -76,7 +76,8 @@ class AnnounceAuthDialog : public AmSession, { AmAudioFile wav_file; string filename; - + UACAuthCred credentials; + public: AnnounceAuthDialog(const string& filename, const string& auth_realm, @@ -91,6 +92,7 @@ class AnnounceAuthDialog : public AmSession, void onDtmf(int event, int duration_msec) {} void process(AmEvent* event); + inline UACAuthCred* getCredentials(); }; diff --git a/core/AmSession.h b/core/AmSession.h index 2556fc44..a9e5892f 100644 --- a/core/AmSession.h +++ b/core/AmSession.h @@ -58,6 +58,7 @@ class AmDtmfEvent; * Signaling plugins must inherite from this class. */ class AmSessionEventHandler + : public ArgObject { public: bool destroy; diff --git a/core/ampi/UACAuthAPI.h b/core/ampi/UACAuthAPI.h new file mode 100644 index 00000000..b04f5d6f --- /dev/null +++ b/core/ampi/UACAuthAPI.h @@ -0,0 +1,60 @@ +/* + * $Id: AmSession.h,v 1.20.2.5 2005/08/31 13:54:29 rco Exp $ + * + * Copyright (C) 2006 iptego GmbH + * + * This file is part of sems, a free SIP media server. + * + * sems is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * For a license to use the ser software under conditions + * other than those described here, or to purchase support for this + * software, please contact iptel.org by e-mail at the following addresses: + * info@iptel.org + * + * sems is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef UACAUTHAPI_H +#define UACAUTHAPI_H + +#include "AmArg.h" +#include "AmSipDialog.h" +#include +using std::string; + +class DialogControl +: public ArgObject +{ + public: + virtual AmSipDialog* getDlg()=0; +}; + +struct UACAuthCred { + string realm; + string user; + string pwd; + UACAuthCred() { } + UACAuthCred(const string& realm, + const string& user, + const string& pwd) + : realm(realm), user(user), pwd(pwd) { } +}; + +class CredentialHolder { + public: + virtual UACAuthCred* getCredentials() = 0; + virtual ~CredentialHolder() { } +}; + +#endif diff --git a/core/plug-in/uac_auth/UACAuth.cpp b/core/plug-in/uac_auth/UACAuth.cpp index 042e35f4..ab958536 100644 --- a/core/plug-in/uac_auth/UACAuth.cpp +++ b/core/plug-in/uac_auth/UACAuth.cpp @@ -28,12 +28,40 @@ #include "UACAuth.h" #include "AmSipRequest.h" +#include "AmUtils.h" + #include using std::map; #define MOD_NAME "uac_auth" EXPORT_SESSION_EVENT_HANDLER_FACTORY(UACAuthFactory, MOD_NAME); +EXPORT_PLUGIN_CLASS_FACTORY(UACAuthFactory, MOD_NAME); + +UACAuthFactory* UACAuthFactory::_instance=0; + +UACAuthFactory* UACAuthFactory::instance() +{ + if(!_instance) + _instance = new UACAuthFactory(MOD_NAME); + return _instance; +} + +void UACAuthFactory::invoke(const string& method, const AmArgArray& args, AmArgArray& ret) +{ + if(method == "getHandler"){ + CredentialHolder* c = dynamic_cast(args.get(0).asObject()); + DialogControl* cc = dynamic_cast(args.get(1).asObject()); + + if ((c!=NULL)&&(cc!=NULL)) { + ret.push(getHandler(cc->getDlg(), c)); + } else { + } + } + else + throw AmDynInvoke::NotImplemented(method); +} + int UACAuthFactory::onLoad() { @@ -47,24 +75,25 @@ bool UACAuthFactory::onInvite(const AmSipRequest& req) AmSessionEventHandler* UACAuthFactory::getHandler(AmSession* s) { - AmSessionEventHandler* res = NULL; - - CredentialHolder* c = dynamic_cast(s); if (c != NULL) { - res = new UACAuth(s, c->getCredentials()); + return getHandler(&s->dlg, c); } else { DBG("no credentials for new session. not enabling auth session handler.\n"); } - return res; + return NULL; } +AmSessionEventHandler* UACAuthFactory::getHandler(AmSipDialog* dlg, CredentialHolder* c) { + return new UACAuth(dlg, c->getCredentials()); +} -UACAuth::UACAuth(AmSession* s, +UACAuth::UACAuth(AmSipDialog* dlg, UACAuthCred* cred) - : AmSessionEventHandler(s), - credential(cred) + : dlg(dlg), + credential(cred), + AmSessionEventHandler() { } @@ -85,7 +114,6 @@ bool UACAuth::onSipRequest(const AmSipRequest& req) bool UACAuth::onSipReply(const AmSipReply& reply) { - DBG("on sip reply --------------------------\n"); bool processed = false; if (reply.code==407 || reply.code==401) { DBG("SIP reply with code %d cseq %d .\n", reply.code, reply.cseq); @@ -95,25 +123,38 @@ bool UACAuth::onSipReply(const AmSipReply& reply) if (ri!= sent_requests.end()) { DBG(" UACAuth - processing with reply code %d \n", reply.code); +// DBG("realm %s user %s pwd %s ----------------\n", +// credential->realm.c_str(), +// credential->user.c_str(), +// credential->pwd.c_str()); + if (((reply.code == 401) && + getHeader(ri->second.hdrs, "Authorization").length()) || + ((reply.code == 407) && + getHeader(ri->second.hdrs, "Proxy-Authorization").length())) { + DBG("Authorization failed!\n"); + } else { + string auth_hdr = (reply.code==407) ? getHeader(reply.hdrs, "Proxy-Authenticate") : + getHeader(reply.hdrs, "WWW-Authenticate"); + string result; - string auth_hdr = (reply.code==407) ? getHeader(reply.hdrs, "Proxy-Authenticate") : - getHeader(reply.hdrs, "WWW-Authenticate"); - string result; - - if (do_auth(reply.code, auth_hdr, - ri->second.method, - s->dlg.remote_uri, result)) { - string hdrs = ri->second.hdrs; - // TODO: strip headers - // ((code==401) ? stripHeader(ri->second.hdrs, "Authorization") : - // stripHeader(ri->second.hdrs, "Proxy-Authorization")); - hdrs += result; - // resend request - if (s->dlg.sendRequest(ri->second.method, - ri->second.content_type, - ri->second.body, - hdrs) != 0) - processed = true; + string auth_uri; + auth_uri = dlg->remote_uri; + + if (do_auth(reply.code, auth_hdr, + ri->second.method, + auth_uri, result)) { + string hdrs = ri->second.hdrs; + // TODO: strip headers + // ((code==401) ? stripHeader(ri->second.hdrs, "Authorization") : + // stripHeader(ri->second.hdrs, "Proxy-Authorization")); + hdrs += result; + // resend request + if (dlg->sendRequest(ri->second.method, + ri->second.content_type, + ri->second.body, + hdrs) == 0) + processed = true; + } } } } @@ -200,7 +241,6 @@ bool UACAuth::parse_header(const string& auth_hdr, UACAuthDigestChallenge& chall // inefficient parsing...TODO: optimize this challenge.realm = find_attribute("realm", auth_hdr); - challenge.domain = find_attribute("domain", auth_hdr); challenge.nonce = find_attribute("nonce", auth_hdr); challenge.opaque = find_attribute("opaque", auth_hdr); challenge.algorithm = find_attribute("algorithm", auth_hdr); @@ -226,8 +266,8 @@ bool UACAuth::do_auth(const unsigned int code, const string& auth_hdr, return false; } - DBG("realm='%s', domain='%s', nonce='%s'\n", challenge.realm.c_str(), - challenge.domain.c_str(), challenge.nonce.c_str()); + DBG("realm='%s', nonce='%s'\n", challenge.realm.c_str(), + challenge.nonce.c_str()); if (credential->realm.length() && (credential->realm != challenge.realm)) { diff --git a/core/plug-in/uac_auth/UACAuth.h b/core/plug-in/uac_auth/UACAuth.h index afacf668..f1673192 100644 --- a/core/plug-in/uac_auth/UACAuth.h +++ b/core/plug-in/uac_auth/UACAuth.h @@ -1,8 +1,36 @@ +/* + * $Id$ + * + * Copyright (C) 2006 iptego GmbH + * + * This file is part of sems, a free SIP media server. + * + * sems is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * For a license to use the ser software under conditions + * other than those described here, or to purchase support for this + * software, please contact iptel.org by e-mail at the following addresses: + * info@iptel.org + * + * sems is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #ifndef UACAuth_h #define UACAuth_h #include "AmApi.h" #include "AmSession.h" +#include "ampi/UACAuthAPI.h" #include using std::string; @@ -16,7 +44,6 @@ typedef unsigned char HASH[HASHLEN]; typedef unsigned char HASHHEX[HASHHEXLEN+1]; struct UACAuthDigestChallenge { - std::string domain; std::string realm; std::string qop; @@ -26,32 +53,18 @@ struct UACAuthDigestChallenge { std::string algorithm; }; -struct UACAuthCred { - string realm; - string user; - string pwd; - UACAuthCred(const string& realm, - const string& user, - const string& pwd) - : realm(realm), user(user), pwd(pwd) { } -}; - -class CredentialHolder { - UACAuthCred cred; - public: - CredentialHolder(const string& realm, - const string& user, - const string& pwd) - : cred(realm,user,pwd) { } - UACAuthCred* getCredentials() { return &cred; } -}; - class UACAuthFactory -: public AmSessionEventHandlerFactory +: public AmSessionEventHandlerFactory, + public AmDynInvokeFactory, + public AmDynInvoke { + static UACAuthFactory* _instance; + AmSessionEventHandler* getHandler(AmSipDialog* dlg, + CredentialHolder* s); public: UACAuthFactory(const string& name) - : AmSessionEventHandlerFactory(name) + : AmSessionEventHandlerFactory(name), + AmDynInvokeFactory(name) { } int onLoad(); @@ -59,6 +72,10 @@ public: // SessionEventHandler API AmSessionEventHandler* getHandler(AmSession* s); bool onInvite(const AmSipRequest&); + + static UACAuthFactory* instance(); + UACAuthFactory* getInstance() { return instance(); } + void invoke(const string& method, const AmArgArray& args, AmArgArray& ret); }; struct SIPRequestInfo { @@ -78,12 +95,13 @@ struct SIPRequestInfo { }; -class UACAuth: public AmSessionEventHandler +class UACAuth : public AmSessionEventHandler { map sent_requests; UACAuthCred* credential; - + AmSipDialog* dlg; + std::string find_attribute(const std::string& name, const std::string& header); bool parse_header(const std::string& auth_hdr, UACAuthDigestChallenge& challenge); @@ -110,7 +128,7 @@ class UACAuth: public AmSessionEventHandler public: - UACAuth(AmSession* s, UACAuthCred* cred); + UACAuth(AmSipDialog* dlg, UACAuthCred* cred); virtual ~UACAuth(){ } /* SEH Hooks @see AmSessionEventHandler */