From fb86538d79e82e22769ccbc40e0ddc8add747bab Mon Sep 17 00:00:00 2001 From: Ron Pedde Date: Sun, 15 Apr 2007 23:57:00 +0000 Subject: [PATCH] Add centralized auth handler for different user roles (currently admin and user), closing #225 and #220 --- src/configfile.c | 93 +++++++++++++++++++++++++++++------------- src/configfile.h | 1 + src/ff-plugins.h | 1 + src/plugin.c | 1 + src/plugins/out-daap.c | 25 +----------- src/plugins/rsp.c | 22 +--------- 6 files changed, 69 insertions(+), 74 deletions(-) diff --git a/src/configfile.c b/src/configfile.c index d16f848e..fb661900 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -168,6 +168,69 @@ int config_session=0; /**< session counter */ #define MAX_LINE 1024 +/** + * used in auth handlers to see if the username and password + * are sufficient to grant a specific role. The roles "user" and + * "admin" are built-in roles, and are the roles used to control access + * to the music and the admin pages respectively. + */ +int config_matches_role(WS_CONNINFO *pwsc, char *username, + char *password, char *role) { + char *required_pw; + int result; + char *my_username, *my_password; + + my_username = username ? username : ""; + my_password = password ? password : ""; + + /* sanity check */ + if((strcasecmp(role,"admin") && strcasecmp(role,"user"))) { + DPRINTF(E_LOG,L_MISC,"Unknown role: %s\n",role); + return FALSE; + } + + /* if we have admin auth, we have everything */ + required_pw = conf_alloc_string("general","admin_pw",NULL); + if(!required_pw) { /* no password set */ + if((pwsc->hostname) && (os_islocaladdr(pwsc->hostname))) + return TRUE; + + DPRINTF(E_LOG,L_MISC,"Auth: attempt to gain admin privs " + "from %s (%s/%s)\n",pwsc->hostname, my_username, my_password); + return FALSE; + } + + /* if the admin password is set, and we've set it */ + if(!strcmp(required_pw, my_password)) { + free(required_pw); + return TRUE; + } + + free(required_pw); + if(!strcasecmp("admin",role)) {/* must we have admin? */ + DPRINTF(E_LOG,L_MISC,"Auth: attempt to gain admin privs " + "from %s (%s/%s)\n",pwsc->hostname, my_username, my_password); + return FALSE; + } + + /* we're checking for user privs */ + result = FALSE; + required_pw = conf_alloc_string("general","password",NULL); + + if(!required_pw) /* none set */ + return TRUE; + + if(!strcmp(required_pw,my_password)) + result = TRUE; + + free(required_pw); + if(!result) { + DPRINTF(E_LOG,L_MISC,"Auth: attempt to gain user privs " + "from %s (%s/%s)\n",pwsc->hostname, my_username, my_password); + } + return result; +} + /** * set the content type based on the file type */ @@ -417,34 +480,7 @@ void config_handler(WS_CONNINFO *pwsc) { * \param password password passed in the auth request */ int config_auth(WS_CONNINFO *pwsc, char *user, char *password) { - char *adminpassword; - int res; - - if((pwsc->hostname) && (os_islocaladdr(pwsc->hostname))) - return TRUE; - - if(strncasecmp(pwsc->uri,"/upnp",5) == 0) - return TRUE; - - adminpassword=conf_alloc_string("general","admin_pw",NULL); - if((!adminpassword) || (strlen(adminpassword)==0)) { - /* we'll handle this later */ - if(adminpassword) free(adminpassword); - return TRUE; - } - - if(!password) { - DPRINTF(E_LOG,L_MISC,"admin: Invalid password from %s (null)\n", - pwsc->hostname); - return FALSE; - } - - res = !strcmp(password,adminpassword); - if(!res) - DPRINTF(E_LOG,L_MISC,"admin: Invalid password from %s (%s)\n", - pwsc->hostname, password); - free(adminpassword); - return res; + return config_matches_role(pwsc,user,password,"admin"); } /** @@ -989,7 +1025,6 @@ void config_emit_system(WS_CONNINFO *pwsc, void *value, char *arg) { ws_writefd(pwsc,"%s",HOST); } - /** * Implement the FLAGS command. * diff --git a/src/configfile.h b/src/configfile.h index e90e0f28..7bf19754 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -29,6 +29,7 @@ extern int config_auth(WS_CONNINFO *pwsc, char *user, char *password); extern void config_handler(WS_CONNINFO *pwsc); extern void config_set_status(WS_CONNINFO *pwsc, int session, char *fmt, ...); extern int config_get_session_count(void); +extern int config_matches_role(WS_CONNINFO *pwsc, char *username, char *password, char *role); /** thread local storage */ typedef struct tag_scan_status { diff --git a/src/ff-plugins.h b/src/ff-plugins.h index 71083fb9..cdbe0cc8 100644 --- a/src/ff-plugins.h +++ b/src/ff-plugins.h @@ -137,6 +137,7 @@ typedef struct tag_plugin_input_fn { char* (*ws_getrequestheader)(struct tag_ws_conninfo *, char *); int (*ws_writebinary)(struct tag_ws_conninfo *, char *, int); char* (*ws_gethostname)(struct tag_ws_conninfo *); + int (*ws_matchesrole)(struct tag_ws_conninfo *, char *, char *, char *); /* misc helpers */ char* (*server_ver)(void); diff --git a/src/plugin.c b/src/plugin.c index ab11d499..00b720ed 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -128,6 +128,7 @@ PLUGIN_INPUT_FN pi = { ws_getrequestheader, ws_writebinary, pi_ws_gethostname, + config_matches_role, pi_server_ver, pi_server_name, diff --git a/src/plugins/out-daap.c b/src/plugins/out-daap.c index 51e8c4b2..6b9af173 100644 --- a/src/plugins/out-daap.c +++ b/src/plugins/out-daap.c @@ -194,7 +194,6 @@ int plugin_can_handle(WS_CONNINFO *pwsc) { * works. */ int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) { - char *readpassword; char *uri = _ppi->ws_uri(pwsc); /* don't auth for stuff we shouldn't */ @@ -205,29 +204,7 @@ int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) { if(strncasecmp(uri,"/databases/1/items/",19) == 0) return TRUE; - readpassword = _ppi->conf_alloc_string("general","password",NULL); - if(password == NULL) { /* testing to see if we need a pw */ - if((readpassword == NULL) || (strlen(readpassword)==0)) { - if(readpassword) _ppi->conf_dispose_string(readpassword); - return TRUE; - } else { - _ppi->conf_dispose_string(readpassword); - _ppi->log(E_LOG,"out-daap: Invalid password from %s (%s)\n", - _ppi->ws_gethostname(pwsc),password); - return FALSE; - } - } else { - if(strcasecmp(password,readpassword)) { - _ppi->conf_dispose_string(readpassword); - _ppi->log(E_LOG,"out-daap: Invalid password from %s (%s)\n", - _ppi->ws_gethostname(pwsc),password); - return FALSE; - } else { - _ppi->conf_dispose_string(readpassword); - return TRUE; - } - } - return TRUE; /* ?? */ + return _ppi->ws_matchesrole(pwsc,username,password,"user"); } diff --git a/src/plugins/rsp.c b/src/plugins/rsp.c index e85ce52f..e040975b 100644 --- a/src/plugins/rsp.c +++ b/src/plugins/rsp.c @@ -170,27 +170,7 @@ int plugin_can_handle(WS_CONNINFO *pwsc) { * works. */ int plugin_auth(WS_CONNINFO *pwsc, char *username, char *password) { - char *readpassword; - - readpassword = _ppi->conf_alloc_string("general","password",NULL); - if(password == NULL) { /* testing to see if we need a pw */ - if((readpassword == NULL) || (strlen(readpassword)==0)) { - if(readpassword) _ppi->conf_dispose_string(readpassword); - return TRUE; - } else { - _ppi->conf_dispose_string(readpassword); - return FALSE; - } - } else { - if(strcasecmp(password,readpassword)) { - _ppi->conf_dispose_string(readpassword); - return FALSE; - } else { - _ppi->conf_dispose_string(readpassword); - return TRUE; - } - } - return TRUE; /* ?? */ + return _ppi->ws_matchesrole(pwsc,username,password,"user"); } /**