📄 rlm_sql.c
字号:
break; } /* * Allowed character. */ *out = *in; out++; in++; outlen--; len++; } *out = '\0'; return len;}/* * Set the SQL user name. * * We don't call the escape function here. The resulting string * will be escaped later in the queries xlat so we don't need to * escape it twice. (it will make things wrong if we have an * escape candidate character in the username) */int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char *username){ VALUE_PAIR *vp=NULL; char tmpuser[MAX_STRING_LEN]; tmpuser[0] = '\0'; sqlusername[0]= '\0'; /* Remove any user attr we added previously */ pairdelete(&request->packet->vps, PW_SQL_USER_NAME); if (username != NULL) { strlcpy(tmpuser, username, sizeof(tmpuser)); } else if (strlen(inst->config->query_user)) { radius_xlat(tmpuser, sizeof(tmpuser), inst->config->query_user, request, NULL); } else { return 0; } 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); return -1; } pairadd(&request->packet->vps, vp); return 0;}static void sql_grouplist_free (SQL_GROUPLIST **group_list){ SQL_GROUPLIST *last; while(*group_list) { last = *group_list; *group_list = (*group_list)->next; free(last); }}static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *request, SQL_GROUPLIST **group_list){ char querystr[MAX_QUERY_LEN]; int num_groups = 0; SQL_ROW row; SQL_GROUPLIST *group_list_tmp; /* NOTE: sql_set_user should have been run before calling this function */ group_list_tmp = *group_list = NULL; if (!inst->config->groupmemb_query || (inst->config->groupmemb_query[0] == 0)) 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); 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, (inst->module->sql_error)(sqlsocket,inst->config)); return -1; } while (rlm_sql_fetch_row(sqlsocket, inst) == 0) { row = sqlsocket->row; if (row == NULL) break; if (row[0] == NULL){ DEBUG("rlm_sql (%s): row[0] returned NULL", inst->config->xlat_name); (inst->module->sql_finish_select_query)(sqlsocket, inst->config); sql_grouplist_free(group_list); return -1; } if (*group_list == NULL) { *group_list = rad_malloc(sizeof(SQL_GROUPLIST)); group_list_tmp = *group_list; } else { group_list_tmp->next = rad_malloc(sizeof(SQL_GROUPLIST)); group_list_tmp = group_list_tmp->next; } group_list_tmp->next = NULL; strlcpy(group_list_tmp->groupname, row[0], MAX_STRING_LEN); } (inst->module->sql_finish_select_query)(sqlsocket, inst->config); return num_groups;}/* * sql groupcmp function. That way we can do group comparisons (in the users file for example) * with the group memberships reciding in sql * The group membership query should only return one element which is the username. The returned * username will then be checked with the passed check string. */static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs){ SQLSOCK *sqlsocket; SQL_INST *inst = instance; char sqlusername[MAX_STRING_LEN]; SQL_GROUPLIST *group_list, *group_list_tmp; check_pairs = check_pairs; reply_pairs = reply_pairs; request = request; DEBUG("rlm_sql (%s): - sql_groupcmp", inst->config->xlat_name); if (!check || !check->vp_strvalue || !check->length){ DEBUG("rlm_sql (%s): sql_groupcmp: Illegal group name", inst->config->xlat_name); return 1; } if (req == NULL){ DEBUG("rlm_sql (%s): sql_groupcmp: NULL request", inst->config->xlat_name); return 1; } /* * Set, escape, and check the user attr here */ if (sql_set_user(inst, req, sqlusername, NULL) < 0) return 1; /* * Get a socket for this lookup */ sqlsocket = sql_get_socket(inst); if (sqlsocket == NULL) { /* Remove the username we (maybe) added above */ pairdelete(&req->packet->vps, PW_SQL_USER_NAME); 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); /* Remove the username we (maybe) added above */ pairdelete(&req->packet->vps, PW_SQL_USER_NAME); 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); /* Free the grouplist */ sql_grouplist_free(&group_list); /* Remove the username we (maybe) added above */ pairdelete(&req->packet->vps, PW_SQL_USER_NAME); sql_release_socket(inst, sqlsocket); return 0; } } /* Free the grouplist */ sql_grouplist_free(&group_list); /* Remove the username we (maybe) added above */ pairdelete(&req->packet->vps, PW_SQL_USER_NAME); 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); return 1;}static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sqlsocket, int *dofallthrough){ VALUE_PAIR *check_tmp = NULL; VALUE_PAIR *reply_tmp = NULL; SQL_GROUPLIST *group_list, *group_list_tmp; VALUE_PAIR *sql_group = NULL; char querystr[MAX_QUERY_LEN]; int found = 0; int rows; /* * 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); return -1; } for (group_list_tmp = group_list; group_list_tmp != NULL && *dofallthrough != 0; group_list_tmp = group_list_tmp->next) { /* * Add the Sql-Group attribute to the request list so we know * which group we're retrieving attributes for */ 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); 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); /* Remove the grouup we added above */ pairdelete(&request->packet->vps, PW_SQL_GROUP); 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); /* Remove the grouup we added above */ pairdelete(&request->packet->vps, PW_SQL_GROUP); pairfree(&check_tmp); return -1; } else if (rows > 0) { /* * Only do this if *some* check pairs were returned */ 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); /* * 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); /* Remove the grouup we added above */ pairdelete(&request->packet->vps, PW_SQL_GROUP); 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); /* Remove the grouup we added above */ pairdelete(&request->packet->vps, PW_SQL_GROUP); pairfree(&check_tmp); pairfree(&reply_tmp); return -1; } *dofallthrough = fallthrough(reply_tmp); pairxlatmove(request, &request->reply->vps, &reply_tmp); pairxlatmove(request, &request->config_items, &check_tmp); } } else { /* * rows == 0. This is like having the username on a line * in the user's file with no check vp's. As such, we treat * it as found and add the reply attributes, so that we * match expected behavior */ found = 1; DEBUG2("rlm_sql (%s): User found in group %s", inst->config->xlat_name, 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); /* Remove the grouup we added above */ pairdelete(&request->packet->vps, PW_SQL_GROUP); 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); /* Remove the grouup we added above */ pairdelete(&request->packet->vps, PW_SQL_GROUP); pairfree(&check_tmp); pairfree(&reply_tmp); return -1; } *dofallthrough = fallthrough(reply_tmp); pairxlatmove(request, &request->reply->vps, &reply_tmp); pairxlatmove(request, &request->config_items, &check_tmp); } /* * Delete the Sql-Group we added above * And clear out the pairlists */ pairdelete(&request->packet->vps, PW_SQL_GROUP); pairfree(&check_tmp); pairfree(&reply_tmp); } sql_grouplist_free(&group_list); return found;}static int rlm_sql_detach(void *instance){ SQL_INST *inst = instance; paircompare_unregister(PW_SQL_GROUP, sql_groupcmp); if (inst->config) { int i; if (inst->sqlpool) { sql_poolfree(inst); } if (inst->config->xlat_name) { xlat_unregister(inst->config->xlat_name,(RAD_XLAT_FUNC)sql_xlat); free(inst->config->xlat_name); } /* * Free up dynamically allocated string pointers. */ for (i = 0; module_config[i].name != NULL; i++) { char **p; if (module_config[i].type != PW_TYPE_STRING_PTR) { continue; } /* * Treat 'config' as an opaque array of bytes, * and take the offset into it. There's a * (char*) pointer at that offset, and we want * to point to it. */ p = (char **) (((char *)inst->config) + module_config[i].offset); if (!*p) { /* nothing allocated */ continue; } free(*p); *p = NULL; } allowed_chars = NULL; free(inst->config); inst->config = NULL; } if (inst->handle) {#if 0 /* * FIXME: Call the modules 'destroy' function?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -