X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Frlm_sql%2Frlm_sql.c;h=15da1c6887aa74bd5c02e0fe530989247f94060d;hb=86d412695dff4d810702f5cc30c093c00627426f;hp=db42caf462d62fb0446331b13840121347eef6d6;hpb=fa2f30ab3c6585fcf93ff15d62229b82cb30291f;p=freeradius.git diff --git a/src/modules/rlm_sql/rlm_sql.c b/src/modules/rlm_sql/rlm_sql.c index db42caf..15da1c6 100644 --- a/src/modules/rlm_sql/rlm_sql.c +++ b/src/modules/rlm_sql/rlm_sql.c @@ -49,6 +49,8 @@ static const CONF_PARSER module_config[] = { offsetof(SQL_CONFIG,sql_password), NULL, ""}, {"radius_db", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,sql_db), NULL, "radius"}, + {"filename", PW_TYPE_FILENAME, /* for sqlite */ + offsetof(SQL_CONFIG,sql_file), NULL, NULL}, {"read_groups", PW_TYPE_BOOLEAN, offsetof(SQL_CONFIG,read_groups), NULL, "yes"}, {"sqltrace", PW_TYPE_BOOLEAN, @@ -61,6 +63,10 @@ static const CONF_PARSER module_config[] = { offsetof(SQL_CONFIG,deletestalesessions), NULL, "yes"}, {"num_sql_socks", PW_TYPE_INTEGER, offsetof(SQL_CONFIG,num_sql_socks), NULL, "5"}, + {"lifetime", PW_TYPE_INTEGER, + offsetof(SQL_CONFIG,lifetime), NULL, "0"}, + {"max_queries", PW_TYPE_INTEGER, + offsetof(SQL_CONFIG,max_queries), NULL, "0"}, {"sql_user_name", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,query_user), NULL, ""}, {"default_user_profile", PW_TYPE_STRING_PTR, @@ -70,7 +76,7 @@ static const CONF_PARSER module_config[] = { {"authorize_check_query", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,authorize_check_query), NULL, ""}, {"authorize_reply_query", PW_TYPE_STRING_PTR, - offsetof(SQL_CONFIG,authorize_reply_query), NULL, ""}, + offsetof(SQL_CONFIG,authorize_reply_query), NULL, NULL}, {"authorize_group_check_query", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,authorize_group_check_query), NULL, ""}, {"authorize_group_reply_query", PW_TYPE_STRING_PTR, @@ -103,6 +109,12 @@ static const CONF_PARSER module_config[] = { offsetof(SQL_CONFIG,allowed_chars), NULL, "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"}, + /* + * This only works for a few drivers. + */ + {"query_timeout", PW_TYPE_INTEGER, + offsetof(SQL_CONFIG,query_timeout), NULL, NULL}, + {NULL, -1, 0, NULL, NULL} }; @@ -112,7 +124,7 @@ static const CONF_PARSER module_config[] = { static int fallthrough(VALUE_PAIR *vp) { VALUE_PAIR *tmp; - tmp = pairfind(vp, PW_FALL_THROUGH); + tmp = pairfind(vp, PW_FALL_THROUGH, 0); return tmp ? tmp->vp_integer : 0; } @@ -128,6 +140,9 @@ static size_t sql_escape_func(char *out, size_t outlen, const char *in); /* * sql xlat function. Right now only SELECTs are supported. Only * the first element of the SELECT result will be used. + * + * For other statements (insert, update, delete, etc.), the + * number of affected rows will be returned. */ static int sql_xlat(void *instance, REQUEST *request, char *fmt, char *out, size_t freespace, @@ -140,7 +155,8 @@ static int sql_xlat(void *instance, REQUEST *request, char sqlusername[MAX_STRING_LEN]; size_t ret = 0; - DEBUG("rlm_sql (%s): - sql_xlat", inst->config->xlat_name); + RDEBUG("sql_xlat"); + /* * Add SQL-User-Name attribute just in case it is needed * We could search the string fmt for SQL-User-Name to see if this is @@ -160,6 +176,59 @@ static int sql_xlat(void *instance, REQUEST *request, sqlsocket = sql_get_socket(inst); if (sqlsocket == NULL) return 0; + + /* + * If the query starts with any of the following prefixes, + * then return the number of rows affected + */ + if ((strncasecmp(querystr, "insert", 6) == 0) || + (strncasecmp(querystr, "update", 6) == 0) || + (strncasecmp(querystr, "delete", 6) == 0)) { + int numaffected; + char buffer[21]; /* 64bit max is 20 decimal chars + null byte */ + + if (rlm_sql_query(sqlsocket,inst,querystr)) { + radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s", + inst->config->xlat_name, querystr, + (inst->module->sql_error)(sqlsocket, + inst->config)); + sql_release_socket(inst,sqlsocket); + return 0; + } + + numaffected = (inst->module->sql_affected_rows)(sqlsocket, + inst->config); + if (numaffected < 1) { + RDEBUG("rlm_sql (%s): SQL query affected no rows", + inst->config->xlat_name); + } + + /* + * Don't chop the returned number if freespace is + * too small. This hack is necessary because + * some implementations of snprintf return the + * size of the written data, and others return + * the size of the data they *would* have written + * if the output buffer was large enough. + */ + snprintf(buffer, sizeof(buffer), "%d", numaffected); + ret = strlen(buffer); + if (ret >= freespace){ + RDEBUG("rlm_sql (%s): Can't write result, insufficient string space", + inst->config->xlat_name); + (inst->module->sql_finish_query)(sqlsocket, + inst->config); + sql_release_socket(inst,sqlsocket); + return 0; + } + + memcpy(out, buffer, ret + 1); /* we did bounds checking above */ + + (inst->module->sql_finish_query)(sqlsocket, inst->config); + sql_release_socket(inst,sqlsocket); + return ret; + } /* else it's a SELECT statement */ + if (rlm_sql_select_query(sqlsocket,inst,querystr)){ radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s", inst->config->xlat_name,querystr, @@ -171,8 +240,7 @@ static int sql_xlat(void *instance, REQUEST *request, ret = rlm_sql_fetch_row(sqlsocket, inst); if (ret) { - DEBUG("rlm_sql (%s): SQL query did not succeed", - inst->config->xlat_name); + RDEBUG("SQL query did not succeed"); (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_release_socket(inst,sqlsocket); return 0; @@ -180,24 +248,21 @@ static int sql_xlat(void *instance, REQUEST *request, row = sqlsocket->row; if (row == NULL) { - DEBUG("rlm_sql (%s): SQL query did not return any results", - inst->config->xlat_name); + RDEBUG("SQL query did not return any results"); (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_release_socket(inst,sqlsocket); return 0; } if (row[0] == NULL){ - DEBUG("rlm_sql (%s): row[0] returned NULL", - inst->config->xlat_name); + RDEBUG("row[0] returned NULL"); (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_release_socket(inst,sqlsocket); return 0; } ret = strlen(row[0]); if (ret >= freespace){ - DEBUG("rlm_sql (%s): sql_xlat:: Insufficient string space", - inst->config->xlat_name); + RDEBUG("Insufficient string space"); (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_release_socket(inst,sqlsocket); return 0; @@ -205,8 +270,7 @@ static int sql_xlat(void *instance, REQUEST *request, strlcpy(out,row[0],freespace); - DEBUG("rlm_sql (%s): - sql_xlat finished", - inst->config->xlat_name); + RDEBUG("sql_xlat finished"); (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_release_socket(inst,sqlsocket); @@ -221,6 +285,7 @@ static int generate_sql_clients(SQL_INST *inst) RADCLIENT *c; char *prefix_ptr = NULL; unsigned int i = 0; + int numf = 0; DEBUG("rlm_sql (%s): Processing generate_sql_clients", inst->config->xlat_name); @@ -254,6 +319,7 @@ static int generate_sql_clients(SQL_INST *inst) * 2. Shortname * 3. Type * 4. Secret + * 5. Virtual Server (optional) */ if (!row[0]){ radlog(L_ERR, "rlm_sql (%s): No row id found on pass %d",inst->config->xlat_name,i); @@ -278,6 +344,10 @@ static int generate_sql_clients(SQL_INST *inst) c = rad_malloc(sizeof(*c)); memset(c, 0, sizeof(*c)); +#ifdef WITH_DYNAMIC_CLIENTS + c->dynamic = 1; +#endif + /* * Look for prefixes */ @@ -301,7 +371,7 @@ static int generate_sql_clients(SQL_INST *inst) if (ip_hton(row[1], AF_UNSPEC, &c->ipaddr) < 0) { radlog(L_CONS|L_ERR, "rlm_sql (%s): Failed to look up hostname %s: %s", inst->config->xlat_name, - row[1], librad_errstr); + row[1], fr_strerror()); free(c); continue; } else { @@ -322,17 +392,21 @@ static int generate_sql_clients(SQL_INST *inst) } /* - * Other values (secret, shortname, nastype) + * Other values (secret, shortname, nastype, virtual_server) */ c->secret = strdup(row[4]); c->shortname = strdup(row[2]); if(row[3] != NULL) c->nastype = strdup(row[3]); - DEBUG("rlm_sql (%s): Adding client %s (%s) to clients list", + numf = (inst->module->sql_num_fields)(sqlsocket, inst->config); + if ((numf > 5) && (row[5] != NULL) && *row[5]) c->server = strdup(row[5]); + + DEBUG("rlm_sql (%s): Adding client %s (%s, server=%s) to clients list", inst->config->xlat_name, - c->longname,c->shortname); + c->longname,c->shortname, c->server ? c->server : ""); if (!client_add(NULL, c)) { + sql_release_socket(inst, sqlsocket); DEBUG("rlm_sql (%s): Failed to add client %s (%s) to clients list. Maybe there's a duplicate?", inst->config->xlat_name, c->longname,c->shortname); @@ -413,7 +487,7 @@ int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char sqlusername[0]= '\0'; /* Remove any user attr we added previously */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); if (username != NULL) { strlcpy(tmpuser, username, sizeof(tmpuser)); @@ -424,15 +498,17 @@ int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char } strlcpy(sqlusername, tmpuser, MAX_STRING_LEN); - DEBUG2("rlm_sql (%s): sql_set_user escaped user --> '%s'", - inst->config->xlat_name, sqlusername); - vp = pairmake("SQL-User-Name", sqlusername, 0); - if (vp == NULL) { - radlog(L_ERR, "%s", librad_errstr); + RDEBUG2("sql_set_user escaped user --> '%s'", sqlusername); + vp = radius_pairmake(request, &request->packet->vps, + "SQL-User-Name", NULL, 0); + if (!vp) { + radlog(L_ERR, "%s", fr_strerror()); return -1; } - pairadd(&request->packet->vps, vp); + strlcpy(vp->vp_strvalue, tmpuser, sizeof(vp->vp_strvalue)); + vp->length = strlen(vp->vp_strvalue); + return 0; } @@ -466,14 +542,15 @@ static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *reque return 0; if (!radius_xlat(querystr, sizeof(querystr), inst->config->groupmemb_query, request, sql_escape_func)) { - radlog(L_ERR, "rlm_sql (%s): xlat failed.", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "xlat \"%s\" failed.", + inst->config->groupmemb_query); return -1; } if (rlm_sql_select_query(sqlsocket, inst, querystr) < 0) { - radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s", - inst->config->xlat_name,querystr, + radlog_request(L_ERR, 0, request, + "database query error, %s: %s", + querystr, (inst->module->sql_error)(sqlsocket,inst->config)); return -1; } @@ -482,8 +559,7 @@ static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *reque if (row == NULL) break; if (row[0] == NULL){ - DEBUG("rlm_sql (%s): row[0] returned NULL", - inst->config->xlat_name); + RDEBUG("row[0] returned NULL"); (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_grouplist_free(group_list); return -1; @@ -492,6 +568,7 @@ static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *reque *group_list = rad_malloc(sizeof(SQL_GROUPLIST)); group_list_tmp = *group_list; } else { + rad_assert(group_list_tmp != NULL); group_list_tmp->next = rad_malloc(sizeof(SQL_GROUPLIST)); group_list_tmp = group_list_tmp->next; } @@ -512,7 +589,7 @@ static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *reque * username will then be checked with the passed check string. */ -static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, +static int sql_groupcmp(void *instance, REQUEST *request, VALUE_PAIR *request_vp, VALUE_PAIR *check, VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs) { SQLSOCK *sqlsocket; @@ -522,23 +599,21 @@ static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE check_pairs = check_pairs; reply_pairs = reply_pairs; - request = request; + request_vp = request_vp; - DEBUG("rlm_sql (%s): - sql_groupcmp", inst->config->xlat_name); + RDEBUG("sql_groupcmp"); if (!check || !check->vp_strvalue || !check->length){ - DEBUG("rlm_sql (%s): sql_groupcmp: Illegal group name", - inst->config->xlat_name); + RDEBUG("sql_groupcmp: Illegal group name"); return 1; } - if (req == NULL){ - DEBUG("rlm_sql (%s): sql_groupcmp: NULL request", - inst->config->xlat_name); + if (!request){ + RDEBUG("sql_groupcmp: NULL request"); return 1; } /* * Set, escape, and check the user attr here */ - if (sql_set_user(inst, req, sqlusername, NULL) < 0) + if (sql_set_user(inst, request, sqlusername, NULL) < 0) return 1; /* @@ -547,31 +622,30 @@ static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE sqlsocket = sql_get_socket(inst); if (sqlsocket == NULL) { /* Remove the username we (maybe) added above */ - pairdelete(&req->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); return 1; } /* * Get the list of groups this user is a member of */ - if (sql_get_grouplist(inst, sqlsocket, req, &group_list) < 0) { - radlog(L_ERR, "rlm_sql (%s): Error getting group membership", - inst->config->xlat_name); + if (sql_get_grouplist(inst, sqlsocket, request, &group_list) < 0) { + radlog_request(L_ERR, 0, request, + "Error getting group membership"); /* Remove the username we (maybe) added above */ - pairdelete(&req->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); sql_release_socket(inst, sqlsocket); return 1; } for (group_list_tmp = group_list; group_list_tmp != NULL; group_list_tmp = group_list_tmp->next) { if (strcmp(group_list_tmp->groupname, check->vp_strvalue) == 0){ - DEBUG("rlm_sql (%s): - sql_groupcmp finished: User is a member of group %s", - inst->config->xlat_name, - (char *)check->vp_strvalue); + RDEBUG("sql_groupcmp finished: User is a member of group %s", + check->vp_strvalue); /* Free the grouplist */ sql_grouplist_free(&group_list); /* Remove the username we (maybe) added above */ - pairdelete(&req->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); sql_release_socket(inst, sqlsocket); return 0; } @@ -580,11 +654,11 @@ static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE /* Free the grouplist */ sql_grouplist_free(&group_list); /* Remove the username we (maybe) added above */ - pairdelete(&req->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); sql_release_socket(inst,sqlsocket); - DEBUG("rlm_sql (%s): - sql_groupcmp finished: User is NOT a member of group %s", - inst->config->xlat_name, (char *)check->vp_strvalue); + RDEBUG("sql_groupcmp finished: User is NOT a member of group %s", + check->vp_strvalue); return 1; } @@ -605,8 +679,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql * Get the list of groups this user is a member of */ if (sql_get_grouplist(inst, sqlsocket, request, &group_list) < 0) { - radlog(L_ERR, "rlm_sql (%s): Error retrieving group list", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Error retrieving group list"); return -1; } @@ -617,24 +690,24 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql */ sql_group = pairmake("Sql-Group", group_list_tmp->groupname, T_OP_EQ); if (!sql_group) { - radlog(L_ERR, "rlm_sql (%s): Error creating Sql-Group attribute", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, + "Error creating Sql-Group attribute"); return -1; } pairadd(&request->packet->vps, sql_group); if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func)) { - radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, + "Error generating query; rejecting user"); /* Remove the grouup we added above */ - pairdelete(&request->packet->vps, PW_SQL_GROUP); + pairdelete(&request->packet->vps, PW_SQL_GROUP, 0); return -1; } rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr); if (rows < 0) { - radlog(L_ERR, "rlm_sql (%s): Error retrieving check pairs for group %s", - inst->config->xlat_name, group_list_tmp->groupname); + radlog_request(L_ERR, 0, request, "Error retrieving check pairs for group %s", + group_list_tmp->groupname); /* Remove the grouup we added above */ - pairdelete(&request->packet->vps, PW_SQL_GROUP); + pairdelete(&request->packet->vps, PW_SQL_GROUP, 0); pairfree(&check_tmp); return -1; } else if (rows > 0) { @@ -643,24 +716,23 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql */ if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) { found = 1; - DEBUG2("rlm_sql (%s): User found in group %s", - inst->config->xlat_name, group_list_tmp->groupname); + RDEBUG2("User found in group %s", + group_list_tmp->groupname); /* * Now get the reply pairs since the paircompare matched */ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) { - radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Error generating query; rejecting user"); /* Remove the grouup we added above */ - pairdelete(&request->packet->vps, PW_SQL_GROUP); + pairdelete(&request->packet->vps, PW_SQL_GROUP, 0); pairfree(&check_tmp); return -1; } if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) { - radlog(L_ERR, "rlm_sql (%s): Error retrieving reply pairs for group %s", - inst->config->xlat_name, group_list_tmp->groupname); + radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s", + group_list_tmp->groupname); /* Remove the grouup we added above */ - pairdelete(&request->packet->vps, PW_SQL_GROUP); + pairdelete(&request->packet->vps, PW_SQL_GROUP, 0); pairfree(&check_tmp); pairfree(&reply_tmp); return -1; @@ -677,24 +749,23 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql * match expected behavior */ found = 1; - DEBUG2("rlm_sql (%s): User found in group %s", - inst->config->xlat_name, group_list_tmp->groupname); + RDEBUG2("User found in group %s", + group_list_tmp->groupname); /* * Now get the reply pairs since the paircompare matched */ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) { - radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Error generating query; rejecting user"); /* Remove the grouup we added above */ - pairdelete(&request->packet->vps, PW_SQL_GROUP); + pairdelete(&request->packet->vps, PW_SQL_GROUP, 0); pairfree(&check_tmp); return -1; } if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) { - radlog(L_ERR, "rlm_sql (%s): Error retrieving reply pairs for group %s", - inst->config->xlat_name, group_list_tmp->groupname); + radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s", + group_list_tmp->groupname); /* Remove the grouup we added above */ - pairdelete(&request->packet->vps, PW_SQL_GROUP); + pairdelete(&request->packet->vps, PW_SQL_GROUP, 0); pairfree(&check_tmp); pairfree(&reply_tmp); return -1; @@ -708,7 +779,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql * Delete the Sql-Group we added above * And clear out the pairlists */ - pairdelete(&request->packet->vps, PW_SQL_GROUP); + pairdelete(&request->packet->vps, PW_SQL_GROUP, 0); pairfree(&check_tmp); pairfree(&reply_tmp); } @@ -758,7 +829,12 @@ static int rlm_sql_detach(void *instance) free(*p); *p = NULL; } - allowed_chars = NULL; + /* + * Catch multiple instances of the module. + */ + if (allowed_chars == inst->config->allowed_chars) { + allowed_chars = NULL; + } free(inst->config); inst->config = NULL; } @@ -787,6 +863,17 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance) memset(inst->config, 0, sizeof(SQL_CONFIG)); /* + * Export these methods, too. This avoids RTDL_GLOBAL. + */ + inst->sql_set_user = sql_set_user; + inst->sql_get_socket = sql_get_socket; + inst->sql_release_socket = sql_release_socket; + inst->sql_escape_func = sql_escape_func; + inst->sql_query = rlm_sql_query; + inst->sql_select_query = rlm_sql_select_query; + inst->sql_fetch_row = rlm_sql_fetch_row; + + /* * If the configuration parameters can't be parsed, then * fail. */ @@ -796,15 +883,45 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance) } xlat_name = cf_section_name2(conf); - if (xlat_name == NULL) + if (xlat_name == NULL) { xlat_name = cf_section_name1(conf); + } else { + char *group_name; + DICT_ATTR *dattr; + ATTR_FLAGS flags; + + /* + * Allocate room for -SQL-Group + */ + group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char)); + sprintf(group_name,"%s-SQL-Group",xlat_name); + DEBUG("rlm_sql Creating new attribute %s",group_name); + + memset(&flags, 0, sizeof(flags)); + dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags); + dattr = dict_attrbyname(group_name); + if (dattr == NULL){ + radlog(L_ERR, "rlm_ldap: Failed to create attribute %s",group_name); + free(group_name); + free(inst); /* FIXME: detach */ + return -1; + } + + if (inst->config->groupmemb_query && + inst->config->groupmemb_query[0]) { + DEBUG("rlm_sql: Registering sql_groupcmp for %s",group_name); + paircompare_register(dattr->attr, PW_USER_NAME, sql_groupcmp, inst); + } + + free(group_name); + } if (xlat_name){ inst->config->xlat_name = strdup(xlat_name); xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst); } if (inst->config->num_sql_socks > MAX_SQL_SOCKS) { - radlog(L_ERR | L_CONS, "rlm_sql (%s): sql_instantiate: number of sqlsockets cannot exceed MAX_SQL_SOCKS, %d", + radlog(L_ERR, "rlm_sql (%s): sql_instantiate: number of sqlsockets cannot exceed MAX_SQL_SOCKS, %d", inst->config->xlat_name, MAX_SQL_SOCKS); rlm_sql_detach(inst); return -1; @@ -814,27 +931,26 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance) * Sanity check for crazy people. */ if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) { - radlog(L_ERR, "rlm_sql (%s): \"%s\" is NOT an SQL driver!", - inst->config->xlat_name, inst->config->sql_driver); + radlog(L_ERR, "\"%s\" is NOT an SQL driver!", + inst->config->sql_driver); rlm_sql_detach(inst); return -1; } inst->handle = lt_dlopenext(inst->config->sql_driver); if (inst->handle == NULL) { - radlog(L_ERR, "rlm_sql (%s): Could not link driver %s: %s", - inst->config->xlat_name, inst->config->sql_driver, + radlog(L_ERR, "Could not link driver %s: %s", + inst->config->sql_driver, lt_dlerror()); - radlog(L_ERR, "rlm_sql (%s): Make sure it (and all its dependent libraries!) are in the search path of your system's ld.", - inst->config->xlat_name); + radlog(L_ERR, "Make sure it (and all its dependent libraries!) are in the search path of your system's ld."); rlm_sql_detach(inst); return -1; } inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle, inst->config->sql_driver); if (!inst->module) { - radlog(L_ERR, "rlm_sql (%s): Could not link symbol %s: %s", - inst->config->xlat_name, inst->config->sql_driver, + radlog(L_ERR, "Could not link symbol %s: %s", + inst->config->sql_driver, lt_dlerror()); rlm_sql_detach(inst); return -1; @@ -852,11 +968,15 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance) rlm_sql_detach(inst); return -1; } - paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst); + + if (inst->config->groupmemb_query && + inst->config->groupmemb_query[0]) { + paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst); + } if (inst->config->do_clients){ if (generate_sql_clients(inst) == -1){ - radlog(L_ERR, "rlm_sql (%s): generate_sql_clients() returned error",inst->config->xlat_name); + radlog(L_ERR, "Failed to load clients from SQL."); rlm_sql_detach(inst); return -1; } @@ -901,7 +1021,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) sqlsocket = sql_get_socket(inst); if (sqlsocket == NULL) { /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); return RLM_MODULE_FAIL; } @@ -914,20 +1034,18 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) * Alright, start by getting the specific entry for the user */ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func)) { - radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Error generating query; rejecting user"); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); return RLM_MODULE_FAIL; } rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr); if (rows < 0) { - radlog(L_ERR, "rlm_sql (%s): SQL query error; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "SQL query error; rejecting user"); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); pairfree(&check_tmp); return RLM_MODULE_FAIL; } else if (rows > 0) { @@ -936,32 +1054,36 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) */ if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) { found = 1; - DEBUG2("rlm_sql (%s): User found in radcheck table", inst->config->xlat_name); + RDEBUG2("User found in radcheck table"); + + if (inst->config->authorize_reply_query && + *inst->config->authorize_reply_query) { + /* * Now get the reply pairs since the paircompare matched */ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func)) { - radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Error generating query; rejecting user"); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); pairfree(&check_tmp); return RLM_MODULE_FAIL; } if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) { - radlog(L_ERR, "rlm_sql (%s): SQL query error; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "SQL query error; rejecting user"); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); pairfree(&check_tmp); pairfree(&reply_tmp); return RLM_MODULE_FAIL; } + if (!inst->config->read_groups) dofallthrough = fallthrough(reply_tmp); pairxlatmove(request, &request->reply->vps, &reply_tmp); + } pairxlatmove(request, &request->config_items, &check_tmp); } } @@ -981,11 +1103,10 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) if (dofallthrough) { rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough); if (rows < 0) { - radlog(L_ERR, "rlm_sql (%s): Error processing groups; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Error processing groups; rejecting user"); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); return RLM_MODULE_FAIL; } else if (rows > 0) { found = 1; @@ -1000,21 +1121,19 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) /* * Check for a default_profile or for a User-Profile. */ - user_profile = pairfind(request->config_items, PW_USER_PROFILE); + user_profile = pairfind(request->config_items, PW_USER_PROFILE, 0); if (inst->config->default_profile[0] != 0 || user_profile != NULL){ char *profile = inst->config->default_profile; if (user_profile != NULL) profile = user_profile->vp_strvalue; if (profile && strlen(profile)){ - radlog(L_DBG, "rlm_sql (%s): Checking profile %s", - inst->config->xlat_name, profile); + RDEBUG("Checking profile %s", profile); if (sql_set_user(inst, request, profileusername, profile) < 0) { - radlog(L_ERR, "rlm_sql (%s): Error setting profile; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Error setting profile; rejecting user"); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); return RLM_MODULE_FAIL; } else { profile_found = 1; @@ -1025,11 +1144,10 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) if (profile_found) { rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough); if (rows < 0) { - radlog(L_ERR, "rlm_sql (%s): Error processing profile groups; rejecting user", - inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Error processing profile groups; rejecting user"); sql_release_socket(inst, sqlsocket); /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); return RLM_MODULE_FAIL; } else if (rows > 0) { found = 1; @@ -1038,12 +1156,11 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) } /* Remove the username we (maybe) added above */ - pairdelete(&request->packet->vps, PW_SQL_USER_NAME); + pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0); sql_release_socket(inst, sqlsocket); if (!found) { - radlog(L_DBG, "rlm_sql (%s): User %s not found", - inst->config->xlat_name, sqlusername); + RDEBUG("User %s not found", sqlusername); return RLM_MODULE_NOTFOUND; } else { return RLM_MODULE_OK; @@ -1074,12 +1191,11 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { /* * Find the Acct Status Type */ - if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) { + if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0)) != NULL) { acctstatustype = pair->vp_integer; } else { radius_xlat(logstr, sizeof(logstr), "packet has no accounting status type. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL); - radlog(L_ERR, "rlm_sql (%s) in sql_accounting: %s", - inst->config->xlat_name, logstr); + radlog_request(L_ERR, 0, request, "%s", logstr); return RLM_MODULE_INVALID; } @@ -1090,7 +1206,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { */ case PW_STATUS_ACCOUNTING_ON: case PW_STATUS_ACCOUNTING_OFF: - radlog(L_INFO, "rlm_sql (%s): received Acct On/Off packet", inst->config->xlat_name); + RDEBUG("Received Acct On/Off packet"); radius_xlat(querystr, sizeof(querystr), inst->config->accounting_onoff_query, request, sql_escape_func); query_log(request, inst, querystr); @@ -1099,8 +1215,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { return(RLM_MODULE_FAIL); if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { - radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting for Acct On/Off packet - %s", - inst->config->xlat_name, + radlog_request(L_ERR, 0, request, "Couldn't update SQL accounting for Acct On/Off packet - %s", (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } @@ -1127,8 +1242,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { return(RLM_MODULE_FAIL); if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { - radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting ALIVE record - %s", - inst->config->xlat_name, + radlog_request(L_ERR, 0, request, "Couldn't update SQL accounting ALIVE record - %s", (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } @@ -1146,8 +1260,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { query_log(request, inst, querystr); if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { - radlog(L_ERR, "rlm_sql (%s): Couldn't insert SQL accounting ALIVE record - %s", - inst->config->xlat_name, + radlog_request(L_ERR, 0, request, "Couldn't insert SQL accounting ALIVE record - %s", (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } @@ -1177,8 +1290,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { return(RLM_MODULE_FAIL); if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { - radlog(L_ERR, "rlm_sql (%s): Couldn't insert SQL accounting START record - %s", - inst->config->xlat_name, + radlog_request(L_ERR, 0, request, "Couldn't insert SQL accounting START record - %s", (inst->module->sql_error)(sqlsocket, inst->config)); /* @@ -1191,8 +1303,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { - radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting START record - %s", - inst->config->xlat_name, + radlog_request(L_ERR, 0, request, "Couldn't update SQL accounting START record - %s", (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } @@ -1221,8 +1332,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { return(RLM_MODULE_FAIL); if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { - radlog(L_ERR, "rlm_sql (%s): Couldn't update SQL accounting STOP record - %s", - inst->config->xlat_name, + radlog_request(L_ERR, 0, request, "Couldn't update SQL accounting STOP record - %s", (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } @@ -1242,14 +1352,14 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { * This is to fix CISCO's aaa from filling our * table with bogus crap */ - if ((pair = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME)) != NULL) + if ((pair = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME, 0)) != NULL) acctsessiontime = pair->vp_integer; if (acctsessiontime <= 0) { radius_xlat(logstr, sizeof(logstr), "stop packet with zero session length. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL); - radlog(L_ERR, "rlm_sql (%s) in sql_accounting: %s", inst->config->xlat_name, logstr); + radlog_request(L_DBG, 0, request, "%s", logstr); sql_release_socket(inst, sqlsocket); - ret = RLM_MODULE_NOOP; + return RLM_MODULE_NOOP; } #endif @@ -1258,8 +1368,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { if (*querystr) { /* non-empty query */ if (rlm_sql_query(sqlsocket, inst, querystr)) { - radlog(L_ERR, "rlm_sql (%s): Couldn't insert SQL accounting STOP record - %s", - inst->config->xlat_name, + radlog_request(L_ERR, 0, request, "Couldn't insert SQL accounting STOP record - %s", + (inst->module->sql_error)(sqlsocket, inst->config)); ret = RLM_MODULE_FAIL; } @@ -1275,7 +1385,8 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) { * Anything else is ignored. */ default: - radlog(L_INFO, "rlm_sql (%s): Unsupported Acct-Status-Type = %d", inst->config->xlat_name, acctstatustype); + RDEBUG("Unsupported Acct-Status-Type = %d", + acctstatustype); return RLM_MODULE_NOOP; break; @@ -1317,7 +1428,7 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) { } if((request->username == NULL) || (request->username->length == 0)) { - radlog(L_ERR, "rlm_sql (%s): Zero Length username not permitted\n", inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Zero Length username not permitted\n"); return RLM_MODULE_INVALID; } @@ -1373,7 +1484,7 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) { radius_xlat(querystr, sizeof(querystr), inst->config->simul_verify_query, request, sql_escape_func); if(rlm_sql_select_query(sqlsocket, inst, querystr)) { - radlog(L_ERR, "rlm_sql (%s): sql_checksimul: Database query error", inst->config->xlat_name); + radlog_request(L_ERR, 0, request, "Database query error"); sql_release_socket(inst, sqlsocket); return RLM_MODULE_FAIL; } @@ -1383,9 +1494,9 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) { */ request->simul_count = 0; - if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS)) != NULL) + if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS, 0)) != NULL) ipno = vp->vp_ipaddr; - if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL) + if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID, 0)) != NULL) call_num = vp->vp_strvalue; @@ -1396,13 +1507,13 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) { if (!row[2]){ (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_release_socket(inst, sqlsocket); - DEBUG("rlm_sql (%s): Cannot zap stale entry. No username present in entry.", inst->config->xlat_name); + RDEBUG("Cannot zap stale entry. No username present in entry.", inst->config->xlat_name); return RLM_MODULE_FAIL; } if (!row[1]){ (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_release_socket(inst, sqlsocket); - DEBUG("rlm_sql (%s): Cannot zap stale entry. No session id in entry.", inst->config->xlat_name); + RDEBUG("Cannot zap stale entry. No session id in entry.", inst->config->xlat_name); return RLM_MODULE_FAIL; } if (row[3]) @@ -1458,7 +1569,7 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) { */ (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_release_socket(inst, sqlsocket); - radlog(L_ERR, "rlm_sql (%s): sql_checksimul: Failed to check the terminal server for user '%s'.", inst->config->xlat_name, row[2]); + radlog_request(L_ERR, 0, request, "Failed to check the terminal server for user '%s'.", row[2]); return RLM_MODULE_FAIL; } } @@ -1483,8 +1594,6 @@ static int rlm_sql_postauth(void *instance, REQUEST *request) { char querystr[MAX_QUERY_LEN]; char sqlusername[MAX_STRING_LEN]; - DEBUG("rlm_sql (%s): Processing sql_postauth", inst->config->xlat_name); - if(sql_set_user(inst, request, sqlusername, NULL) < 0) return RLM_MODULE_FAIL;