mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-25 06:35:57 -05:00
Add centralized auth handler for different user roles (currently admin and user), closing #225 and #220
This commit is contained in:
parent
29478fcca1
commit
fb86538d79
@ -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.
|
||||
*
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -128,6 +128,7 @@ PLUGIN_INPUT_FN pi = {
|
||||
ws_getrequestheader,
|
||||
ws_writebinary,
|
||||
pi_ws_gethostname,
|
||||
config_matches_role,
|
||||
|
||||
pi_server_ver,
|
||||
pi_server_name,
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user