[Asterisk-cvs] asterisk/channels chan_sip.c,1.691,1.692
markster at lists.digium.com
markster at lists.digium.com
Thu Mar 24 17:12:02 CST 2005
Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv32234/channels
Modified Files:
chan_sip.c
Log Message:
Add SIP real authentication (bug #3782)
Index: chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.691
retrieving revision 1.692
diff -u -d -r1.691 -r1.692
--- chan_sip.c 24 Mar 2005 05:02:49 -0000 1.691
+++ chan_sip.c 24 Mar 2005 23:06:21 -0000 1.692
@@ -291,11 +291,21 @@
char hop[0];
};
+/* sip_history: Structure for saving transactions within a SIP dialog */
struct sip_history {
char event[80];
struct sip_history *next;
};
+/* sip_auth: Creadentials for authentication to other SIP services */
+struct sip_auth {
+ char realm[AST_MAX_EXTENSION]; /* Realm in which these credentials are valid */
+ char username[256]; /* Username */
+ char secret[256]; /* Secret */
+ char md5secret[256]; /* MD5Secret */
+ struct sip_auth *next; /* Next auth structure in list */
+};
+
#define SIP_ALREADYGONE (1 << 0) /* Whether or not we've already been destroyed by our peer */
#define SIP_NEEDDESTROY (1 << 1) /* if we need to be destroyed */
#define SIP_NOVIDEO (1 << 2) /* Didn't get video in invite, don't offer */
@@ -410,6 +420,7 @@
char okcontacturi[256]; /* URI from the 200 OK on INVITE */
char peersecret[256]; /* Password */
char peermd5secret[256];
+ struct sip_auth *peerauth; /* Realm authentication */
char cid_num[256]; /* Caller*ID */
char cid_name[256]; /* Caller*ID */
char via[256]; /* Via: header */
@@ -505,6 +516,7 @@
/* peer->name is the unique name of this object */
char secret[80]; /* Password */
char md5secret[80]; /* Password in MD5 */
+ struct sip_auth *auth; /* Realm authentication list */
char context[80]; /* Default context for incoming calls */
char username[80]; /* Temporary username until registration */
char accountcode[20]; /* Account code */
@@ -630,6 +642,9 @@
/* The list of manual NOTIFY types we know how to send */
struct ast_config *notify_types;
+static struct sip_auth *authl; /* Authentication list */
+
+
static struct ast_frame *sip_read(struct ast_channel *ast);
static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
@@ -667,6 +682,9 @@
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int sip_senddigit(struct ast_channel *ast, char digit);
static int sip_sendtext(struct ast_channel *ast, char *text);
+static int clear_realm_authentication(struct sip_auth *authlist); /* Clear realm authentication list (at reload) */
+static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno); /* Add realm authentication in list */
+static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm); /* Find authentication for a specific realm */
/* Definition of this channel for channel registration */
static const struct ast_channel_tech sip_tech = {
@@ -716,6 +734,7 @@
return 1;
}
+/*--- sip_debug_test_pvt: Test PVT for debugging output */
static inline int sip_debug_test_pvt(struct sip_pvt *p)
{
if (sipdebug == 0)
@@ -1234,6 +1253,8 @@
rpeerobjs--;
else
speerobjs--;
+ clear_realm_authentication(peer->auth);
+ peer->auth = (struct sip_auth *) NULL;
free(peer);
}
@@ -6513,6 +6534,7 @@
char codec_buf[512];
struct ast_codec_pref *pref;
struct ast_variable *v;
+ struct sip_auth *auth;
int x = 0, codec = 0, load_realtime = 0;
if (argc < 4)
@@ -6536,6 +6558,12 @@
ast_cli(fd, " * Name : %s\n", peer->name);
ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
ast_cli(fd, " MD5Secret : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>");
+ auth = peer->auth;
+ while(auth) {
+ ast_cli(fd, " Realm-auth : Realm %-15.15s User %-10.20s ", auth->realm, auth->username);
+ ast_cli(fd, "%s\n", !ast_strlen_zero(auth->secret)?"<Secret set>":(!ast_strlen_zero(auth->md5secret)?"<MD5secret set>" : "<Not set>"));
+ auth = auth->next;
+ }
ast_cli(fd, " Context : %s\n", peer->context);
ast_cli(fd, " Language : %s\n", peer->language);
if (!ast_strlen_zero(peer->accountcode))
@@ -7458,6 +7486,10 @@
char uri[256] = "";
char cnonce[80];
char iabuf[INET_ADDRSTRLEN];
+ char *username;
+ char *secret;
+ char *md5secret;
+ struct sip_auth *auth = (struct sip_auth *) NULL; /* Realm authentication */
if (!ast_strlen_zero(p->domain))
strncpy(uri, p->domain, sizeof(uri) - 1);
@@ -7468,10 +7500,25 @@
snprintf(cnonce, sizeof(cnonce), "%08x", rand());
- snprintf(a1,sizeof(a1),"%s:%s:%s",p->authname,p->realm,p->peersecret);
+ /* Check if we have separate auth credentials */
+ if ((auth = find_realm_authentication(authl, p->realm))) {
+ username = auth->username;
+ secret = auth->secret;
+ md5secret = auth->md5secret;
+ ast_log(LOG_NOTICE,"Using realm %s authentication for this call\n", p->realm);
+ } else {
+ /* No authentication, use peer or register= config */
+ username = p->authname;
+ secret = p->peersecret;
+ md5secret = p->peermd5secret;
+ }
+
+
+ /* Calculate SIP digest response */
+ snprintf(a1,sizeof(a1),"%s:%s:%s",username,p->realm,secret);
snprintf(a2,sizeof(a2),"%s:%s", sip_methods[method].text, uri);
- if (!ast_strlen_zero(p->peermd5secret))
- strncpy(a1_hash, p->peermd5secret, sizeof(a1_hash) - 1);
+ if (!ast_strlen_zero(md5secret))
+ strncpy(a1_hash, md5secret, sizeof(a1_hash) - 1);
else
ast_md5_hash(a1_hash,a1);
ast_md5_hash(a2_hash,a2);
@@ -7484,9 +7531,9 @@
ast_md5_hash(resp_hash,resp);
/* XXX We hard code our qop to "auth" for now. XXX */
if (!ast_strlen_zero(p->qop))
- snprintf(digest,digest_len,"Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\", opaque=\"%s\", qop=\"%s\", cnonce=\"%s\", nc=%s",p->authname,p->realm,uri,p->nonce,resp_hash, p->opaque, "auth", cnonce, "00000001");
+ snprintf(digest, digest_len, "Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\", opaque=\"%s\", qop=\"%s\", cnonce=\"%s\", nc=%s", username, p->realm, uri, p->nonce, resp_hash, p->opaque, "auth", cnonce, "00000001");
else
- snprintf(digest,digest_len,"Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\", opaque=\"%s\"",p->authname,p->realm,uri,p->nonce,resp_hash, p->opaque);
+ snprintf(digest, digest_len, "Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\", opaque=\"%s\"", username, p->realm, uri, p->nonce, resp_hash, p->opaque);
return 0;
}
@@ -9525,6 +9572,105 @@
return res;
}
+/*--- add_realm_authentication: Add realm authentication in list ---*/
+static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno)
+{
+ char authcopy[256] = "";
+ char *username=NULL, *realm=NULL, *secret=NULL, *md5secret=NULL;
+ char *stringp;
+ struct sip_auth *auth;
+ struct sip_auth *b = NULL, *a = authlist;
+
+ if (!configuration || ast_strlen_zero(configuration))
+ return (authlist);
+
+ ast_log(LOG_DEBUG, "Auth config :: %s\n", configuration);
+
+ strncpy(authcopy, configuration, sizeof(authcopy)-1);
+ stringp = authcopy;
+
+ username = stringp;
+ realm = strrchr(stringp, '@');
+ if (realm) {
+ *realm = '\0';
+ realm++;
+ }
+ if (!username || ast_strlen_zero(username) || !realm || ast_strlen_zero(realm)) {
+ ast_log(LOG_WARNING, "Format for authentication entry is user[:secret]@realm at line %d", lineno);
+ return (authlist);
+ }
+ stringp = username;
+ username = strsep(&stringp, ":");
+ if (username) {
+ secret = strsep(&stringp, ":");
+ if (!secret) {
+ stringp = username;
+ md5secret = strsep(&stringp,"#");
+ }
+ }
+ auth = malloc(sizeof(struct sip_auth));
+ if (auth) {
+ memset(auth, 0, sizeof(struct sip_auth));
+ strncpy(auth->realm, realm, sizeof(auth->realm)-1);
+ strncpy(auth->username, username, sizeof(auth->username)-1);
+ if (secret)
+ strncpy(auth->secret, secret, sizeof(auth->secret)-1);
+ if (md5secret)
+ strncpy(auth->md5secret, md5secret, sizeof(auth->md5secret)-1);
+ } else {
+ ast_log(LOG_ERROR, "Allocation of auth structure failed, Out of memory\n");
+ return (authlist);
+ }
+
+ /* Add authentication to authl */
+ if (!authlist) { /* No existing list */
+ return(auth);
+ } else {
+ while(a) {
+ b = a;
+ a = a->next;
+ }
+ b->next = auth; /* Add structure add end of list */
+ }
+
+ if (option_verbose > 2)
+ ast_verbose("Added authentication for realm %s\n", realm);
+
+ return(authlist);
+
+}
+
+/*--- clear_realm_authentication: Clear realm authentication list (at reload) ---*/
+static int clear_realm_authentication(struct sip_auth *authlist)
+{
+ struct sip_auth *a = authlist;
+ struct sip_auth *b;
+
+ while(a) {
+ b = a;
+ a = a->next;
+ free(b);
+ }
+
+
+ return(1);
+}
+
+/*--- find_realm_authentication: Find authentication for a specific realm ---*/
+static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm)
+{
+ struct sip_auth *a = authlist; /* First entry in auth list */
+
+ while (a) {
+ if (!strcasecmp(a->realm, realm)){
+ break;
+ }
+ a = a->next;
+ }
+
+ return(a);
+}
+
/*--- build_user: Initiate a SIP user structure from sip.conf ---*/
static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime)
{
@@ -9754,6 +9900,8 @@
strncpy(peer->secret, v->value, sizeof(peer->secret)-1);
else if (!strcasecmp(v->name, "md5secret"))
strncpy(peer->md5secret, v->value, sizeof(peer->md5secret)-1);
+ else if (!strcasecmp(v->name, "auth"))
+ peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno);
else if (!strcasecmp(v->name, "callerid")) {
ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num));
} else if (!strcasecmp(v->name, "context"))
@@ -10166,10 +10314,21 @@
v = v->next;
}
+ /* Build list of authentication to various SIP realms, i.e. service providers */
+ v = ast_variable_browse(cfg, "authentication");
+ while(v) {
+ /* Format for authentication is auth = username:password at realm */
+ if (!strcasecmp(v->name, "auth")) {
+ authl = add_realm_authentication(authl, v->value, v->lineno);
+ }
+ v = v->next;
+ }
+
+
/* Load peers, users and friends */
cat = ast_category_browse(cfg, NULL);
while(cat) {
- if (strcasecmp(cat, "general")) {
+ if (strcasecmp(cat, "general") && strcasecmp(cat, "authentication")) {
utype = ast_variable_retrieve(cfg, cat, "type");
if (utype) {
if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
@@ -10611,6 +10770,9 @@
/*--- sip_do_reload: Reload module */
static int sip_do_reload(void)
{
+ clear_realm_authentication(authl);
+ authl = (struct sip_auth *) NULL;
+
delete_users();
reload_config();
prune_peers();
@@ -10735,6 +10897,8 @@
ast_manager_unregister("SIPpeers");
ast_manager_unregister("SIPshowpeer");
ast_channel_unregister(&sip_tech);
+
+
if (!ast_mutex_lock(&iflock)) {
/* Hangup all interfaces if they have an owner */
p = iflist;
@@ -10787,6 +10951,8 @@
ASTOBJ_CONTAINER_DESTROY(&userl);
ASTOBJ_CONTAINER_DESTROY(&peerl);
ASTOBJ_CONTAINER_DESTROY(®l);
+
+ clear_realm_authentication(authl);
return 0;
}
More information about the svn-commits
mailing list