modules_s/auth/auth_mod.c
2d429fbd
 /* 
  * $Id$ 
9f0c8882
  *
  * Digest Authentication Module
ed346bcc
  *
  * Copyright (C) 2001-2003 Fhg Fokus
  *
  * This file is part of ser, a free SIP server.
  *
  * ser 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
  *
  * ser 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
2d429fbd
  */
 
ed346bcc
 
462def1b
 #include "auth_mod.h"
59f8bf50
 #include <stdio.h>
2d429fbd
 #include <stdlib.h>
 #include "../../sr_module.h"
 #include "../../dprint.h"
 #include "defs.h"
 #include <string.h>
462def1b
 #include "checks.h"
 #include "group.h"
 #include "../../ut.h"
 #include "../../error.h"
9f0c8882
 #include "authorize.h"
 #include "challenge.h"
2d429fbd
 
 
462def1b
 /*
  * Module destroy function prototype
  */
acd3e9c7
 static void destroy(void);
462def1b
 
 
 /*
  * Module child-init function prototype
  */
acd3e9c7
 static int child_init(int rank);
462def1b
 
 
 /*
  * Module initialization function prototype
  */
acd3e9c7
 static int mod_init(void);
36bd09d1
 
462def1b
 
 static int challenge_fixup(void** param, int param_no);
9f0c8882
 static int str_fixup(void** param, int param_no);
59f8bf50
 static int hf_fixup(void** param, int param_no);
462def1b
 
 
 /*
  * Pointer to reply function in stateless module
  */
5d34d82e
 int (*sl_reply)(struct sip_msg* _msg, char* _str1, char* _str2);
 
462def1b
 
 /*
  * Module parameter variables
  */
734c06d0
 char* db_url       = "sql://serro:47serro11@localhost/ser";
 char* user_column  = "user_id";
8d661a85
 char* realm_column = "realm";
462def1b
 char* pass_column  = "ha1";
 
 #ifdef USER_DOMAIN_HACK
 char* pass_column_2 = "ha1b";
 #endif
 
 char* sec          = "4e9rhygt90ofw34e8hiof09tg"; /* Secret phrase used to generate nonce value */
 char* grp_table    = "grp";                       /* Table name where group definitions are stored */
 char* grp_user_col = "user";
 char* grp_grp_col  = "grp";
4307b1ad
 int   calc_ha1     = 0;
 int   nonce_expire = 300;
 int   retry_count  = 5;
462def1b
 
 str secret;
 db_con_t* db_handle;   /* Database connection handle */
 
8d661a85
 
462def1b
 /*
  * Module interface
  */
d7be241b
 #ifdef STATIC_AUTH
 struct module_exports auth_exports = {
 #else
acd3e9c7
 struct module_exports exports = {
d7be241b
 #endif
acd3e9c7
 	"auth", 
 	(char*[]) { 
462def1b
 		"www_authorize",
 		"proxy_authorize",
 		"www_challenge",
 		"proxy_challenge",
acd3e9c7
 		"is_user",
 		"is_in_group",
 		"check_to",
9f0c8882
 		"check_from",
 		"consume_credentials",
 		"is_user_in"
acd3e9c7
 	},
 	(cmd_function[]) {
462def1b
 		www_authorize,
 		proxy_authorize,
 		www_challenge,
 		proxy_challenge,
acd3e9c7
 		is_user,
 		is_in_group,
 		check_to,
9f0c8882
 		check_from,
 		consume_credentials,
59f8bf50
 		is_user_in
acd3e9c7
 	},
59f8bf50
 	(int[]) {2, 2, 2, 2, 1, 1, 0, 0, 0, 2},
acd3e9c7
 	(fixup_function[]) {
9f0c8882
 		str_fixup, str_fixup, 
 		challenge_fixup, challenge_fixup, 
 		str_fixup, str_fixup, 0, 0,
59f8bf50
 		0, hf_fixup
acd3e9c7
 	},
59f8bf50
 	10,
acd3e9c7
 	
8d661a85
 	(char*[]) {
462def1b
 		"db_url",              /* Database URL */
 		"user_column",         /* User column name */
 		"realm_column",        /* Realm column name */
 		"password_column",     /* HA1/password column name */
 #ifdef USER_DOMAIN_HACK
 		"password_column_2",
 #endif
 
 		"secret",              /* Secret phrase used to generate nonce */
 		"group_table",         /* Group table name */
 		"group_user_column",   /* Group table user column name */
 		"group_group_column",  /* Group table group column name */
 		"calculate_ha1",       /* If set to yes, instead of ha1 value auth module will
                                         * fetch plaintext password from database and calculate
                                         * ha1 value itself */
 		"nonce_expire",        /* After how many seconds nonce expires */
 		"retry_count"          /* How many times a client is allowed to retry */
 		
 		
8d661a85
 	},   /* Module parameter names */
 	(modparam_t[]) {
 		STR_PARAM,
 		STR_PARAM,
 		STR_PARAM,
 		STR_PARAM,
462def1b
 #ifdef USER_DOMAIN_HACK
 		STR_PARAM,
 #endif
 		STR_PARAM,
 		STR_PARAM,
 		STR_PARAM,
 		STR_PARAM,
 	        INT_PARAM,
 		INT_PARAM,
 		INT_PARAM
8d661a85
 	},   /* Module parameter types */
 	(void*[]) {
 		&db_url,
 		&user_column,
 		&realm_column,
462def1b
 		&pass_column,
 #ifdef USER_DOMAIN_HACK
 		&pass_column_2,
 #endif
 		&sec,
 		&grp_table,
 		&grp_user_col,
 		&grp_grp_col,
 		&calc_ha1,
 		&nonce_expire,
 		&retry_count
 		
8d661a85
 	},   /* Module parameter variable pointers */
462def1b
 #ifdef USER_DOMAIN_HACK
 	12,      /* Numberof module parameters */
 #else
 	11,      /* Number of module paramers */
 #endif					     
acd3e9c7
 	mod_init,   /* module initialization function */
 	NULL,       /* response function */
 	destroy,    /* destroy function */
 	NULL,       /* oncancel function */
 	child_init  /* child initialization function */
2d429fbd
 };
 
 
acd3e9c7
 static int child_init(int rank)
36bd09d1
 {
8d661a85
 	if (db_url == NULL) {
 		LOG(L_ERR, "auth:init_child(): Use db_url parameter\n");
 		return -1;
 	}
 	db_handle = db_init(db_url);
36bd09d1
 	if (!db_handle) {
 		LOG(L_ERR, "auth:init_child(): Unable to connect database\n");
 		return -1;
 	}
 	return 0;
 
 }
 
 
acd3e9c7
 static int mod_init(void)
2d429fbd
 {
e3504eb7
 	printf("auth module - initializing\n");
2d429fbd
 	
 	     /* Find a database module */
 	if (bind_dbmod()) {
acd3e9c7
 		LOG(L_ERR, "mod_init(): Unable to bind database module\n");
 		return -1;
2d429fbd
 	}
 
5d34d82e
 	sl_reply = find_export("sl_send_reply", 2);
 
 	if (!sl_reply) {
acd3e9c7
 		LOG(L_ERR, "auth:mod_init(): This module requires sl module\n");
 		return -2;
5d34d82e
 	}
 
462def1b
 	     /* Precalculate secret string length */
 	secret.s = sec;
 	secret.len = strlen(secret.s);
 
acd3e9c7
 	return 0;
2d429fbd
 }
 
 
36bd09d1
 
acd3e9c7
 static void destroy(void)
2d429fbd
 {
 	db_close(db_handle);
 }
462def1b
 
 
 static int challenge_fixup(void** param, int param_no)
 {
 	unsigned int qop;
 	int err;
 	
 	if (param_no == 2) {
 		qop = str2s(*param, strlen(*param), &err);
 
 		if (err == 0) {
 			free(*param);
 			*param=(void*)qop;
 		} else {
 			LOG(L_ERR, "challenge_fixup(): Bad number <%s>\n",
 			    (char*)(*param));
 			return E_UNSPEC;
 		}
 	}
 
 	return 0;
 }
9f0c8882
 
 
 /*
  * Convert char* parameter to str* parameter
  */
 static int str_fixup(void** param, int param_no)
 {
 	str* s;
 
 	if (param_no == 1) {
 		s = (str*)malloc(sizeof(str));
 		if (!s) {
 			LOG(L_ERR, "authorize_fixup(): No memory left\n");
 			return E_UNSPEC;
 		}
 
 		s->s = (char*)*param;
 		s->len = strlen(s->s);
 		*param = (void*)s;
 	}
 
 	return 0;
 }
59f8bf50
 
 
 /*
  * Convert HF description string to hdr_field pointer
  *
  * Supported strings: 
  * "Request-URI", "To", "From", "Credentials"
  */
 static int hf_fixup(void** param, int param_no)
 {
 	void* ptr;
4d5697eb
 	str* s;
59f8bf50
 
 	if (param_no == 1) {
 		ptr = *param;
4d5697eb
 		
59f8bf50
 		if (!strcasecmp((char*)*param, "Request-URI")) {
 			*param = (void*)1;
 		} else if (!strcasecmp((char*)*param, "To")) {
 			*param = (void*)2;
 		} else if (!strcasecmp((char*)*param, "From")) {
 			*param = (void*)3;
 		} else if (!strcasecmp((char*)*param, "Credentials")) {
 			*param = (void*)4;
 		} else {
 			LOG(L_ERR, "hf_fixup(): Unsupported Header Field identifier\n");
 			return E_UNSPEC;
 		}
 
 		free(ptr);
4d5697eb
 	} else if (param_no == 2) {
 		s = (str*)malloc(sizeof(str));
 		if (!s) {
 			LOG(L_ERR, "hf_fixup(): No memory left\n");
 			return E_UNSPEC;
 		}
 
 		s->s = (char*)*param;
 		s->len = strlen(s->s);
 		*param = (void*)s;
59f8bf50
 	}
 
 	return 0;
 }