wok rev 11352
busybox/httpd: add support for system passwords
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Tue Nov 29 18:11:22 2011 +0100 (2011-11-29) |
parents | 05ee700100bf |
children | c2af9b1a616f |
files | busybox/receipt busybox/stuff/busybox-1.18-httpd.u |
line diff
1.1 --- a/busybox/receipt Tue Nov 29 11:53:47 2011 +0000 1.2 +++ b/busybox/receipt Tue Nov 29 18:11:22 2011 +0100 1.3 @@ -28,6 +28,7 @@ 1.4 printable.u 1.5 cmdline.u 1.6 conspy.u 1.7 +httpd.u 1.8 EOT 1.9 cp $stuff/$PACKAGE-${VERSION%.*}.config .config 1.10 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/busybox/stuff/busybox-1.18-httpd.u Tue Nov 29 18:11:22 2011 +0100 2.3 @@ -0,0 +1,218 @@ 2.4 +Add support for system passwords 2.5 +--- busybox-1.18.2/networking/httpd.c 2.6 ++++ busybox-1.18.2/networking/httpd.c 2.7 +@@ -53,6 +53,8 @@ 2.8 + * /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/ 2.9 + * /adm:admin:setup # Require user admin, pwd setup on urls starting with /adm/ 2.10 + * /adm:toor:PaSsWd # or user toor, pwd PaSsWd on urls starting with /adm/ 2.11 ++ * /adm:root:* # or user root, pwd from /etc/passwd on urls starting with /adm/ 2.12 ++ * /wiki:*:* # or any user from /etc/passwd with according pwd on urls starting with /wiki/ 2.13 + * .au:audio/basic # additional mime type for audio.au files 2.14 + * *.php:/path/php # running cgi.php scripts through an interpreter 2.15 + * 2.16 +@@ -96,6 +98,14 @@ 2.17 + */ 2.18 + 2.19 + #include "libbb.h" 2.20 ++#if ENABLE_PAM 2.21 ++/* PAM may include <locale.h>. We may need to undefine bbox's stub define: */ 2.22 ++# undef setlocale 2.23 ++/* For some obscure reason, PAM is not in pam/xxx, but in security/xxx. 2.24 ++ * Apparently they like to confuse people. */ 2.25 ++# include <security/pam_appl.h> 2.26 ++# include <security/pam_misc.h> 2.27 ++#endif 2.28 + #if ENABLE_FEATURE_HTTPD_USE_SENDFILE 2.29 + #include <sys/sendfile.h> 2.30 + #endif 2.31 +@@ -1663,6 +1673,56 @@ 2.32 + } 2.33 + 2.34 + #if ENABLE_FEATURE_HTTPD_BASIC_AUTH 2.35 ++ 2.36 ++# if ENABLE_FEATURE_HTTPD_AUTH_MD5 && ENABLE_PAM 2.37 ++struct pam_userinfo { 2.38 ++ const char *name; 2.39 ++ const char *pw; 2.40 ++}; 2.41 ++ 2.42 ++static int pam_talker(int num_msg, 2.43 ++ const struct pam_message **msg, 2.44 ++ struct pam_response **resp, 2.45 ++ void *appdata_ptr) 2.46 ++{ 2.47 ++ int i; 2.48 ++ struct pam_userinfo *userinfo = (struct pam_userinfo *) appdata_ptr; 2.49 ++ struct pam_response *response; 2.50 ++ 2.51 ++ if (!resp || !msg || !userinfo) 2.52 ++ return PAM_CONV_ERR; 2.53 ++ 2.54 ++ /* allocate memory to store response */ 2.55 ++ response = xzalloc(num_msg * sizeof(*response)); 2.56 ++ 2.57 ++ /* copy values */ 2.58 ++ for (i = 0; i < num_msg; i++) { 2.59 ++ const char *s; 2.60 ++ 2.61 ++ switch (msg[i]->msg_style) { 2.62 ++ case PAM_PROMPT_ECHO_ON: 2.63 ++ s = userinfo->name; 2.64 ++ break; 2.65 ++ case PAM_PROMPT_ECHO_OFF: 2.66 ++ s = userinfo->pw; 2.67 ++ break; 2.68 ++ case PAM_ERROR_MSG: 2.69 ++ case PAM_TEXT_INFO: 2.70 ++ s = ""; 2.71 ++ break; 2.72 ++ default: 2.73 ++ free(response); 2.74 ++ return PAM_CONV_ERR; 2.75 ++ } 2.76 ++ response[i].resp = xstrdup(s); 2.77 ++ if (PAM_SUCCESS != 0) 2.78 ++ response[i].resp_retcode = PAM_SUCCESS; 2.79 ++ } 2.80 ++ *resp = response; 2.81 ++ return PAM_SUCCESS; 2.82 ++} 2.83 ++# endif 2.84 ++ 2.85 + /* 2.86 + * Config file entries are of the form "/<path>:<user>:<passwd>". 2.87 + * If config file has no prefix match for path, access is allowed. 2.88 +@@ -1672,7 +1732,7 @@ 2.89 + * 2.90 + * Returns 1 if user_and_passwd is OK. 2.91 + */ 2.92 +-static int check_user_passwd(const char *path, const char *user_and_passwd) 2.93 ++static int check_user_passwd(const char *path, char *user_and_passwd) 2.94 + { 2.95 + Htaccess *cur; 2.96 + const char *prev = NULL; 2.97 +@@ -1680,6 +1740,7 @@ 2.98 + for (cur = g_auth; cur; cur = cur->next) { 2.99 + const char *dir_prefix; 2.100 + size_t len; 2.101 ++ int r; 2.102 + 2.103 + dir_prefix = cur->before_colon; 2.104 + 2.105 +@@ -1704,36 +1765,96 @@ 2.106 + prev = dir_prefix; 2.107 + 2.108 + if (ENABLE_FEATURE_HTTPD_AUTH_MD5) { 2.109 +- char *md5_passwd; 2.110 ++ char *colon_after_user; 2.111 ++ const char *passwd; 2.112 ++# if ENABLE_FEATURE_SHADOWPASSWDS && !ENABLE_PAM 2.113 ++ char buffer[256]; /* will store passwd */ 2.114 ++# endif 2.115 + 2.116 +- md5_passwd = strchr(cur->after_colon, ':'); 2.117 +- if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1' 2.118 +- && md5_passwd[3] == '$' && md5_passwd[4] 2.119 +- ) { 2.120 +- char *encrypted; 2.121 +- int r, user_len_p1; 2.122 ++ colon_after_user = strchr(user_and_passwd, ':'); 2.123 ++ if (!colon_after_user) 2.124 ++ goto bad_input; 2.125 ++ passwd = strchr(cur->after_colon, ':'); 2.126 ++ if (!passwd) 2.127 ++ goto bad_input; 2.128 ++ passwd++; 2.129 ++ if (passwd[0] == '*') { 2.130 ++# if ENABLE_PAM 2.131 ++ struct pam_userinfo userinfo; 2.132 ++ struct pam_conv conv_info = { &pam_talker, (void *) &userinfo }; 2.133 ++ pam_handle_t *pamh; 2.134 + 2.135 +- md5_passwd++; 2.136 +- user_len_p1 = md5_passwd - cur->after_colon; 2.137 +- /* comparing "user:" */ 2.138 +- if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) { 2.139 ++ /* compare "user:" */ 2.140 ++ if (cur->after_colon[0] != '*' 2.141 ++ && strncmp(cur->after_colon, user_and_passwd, colon_after_user - user_and_passwd + 1) != 0 2.142 ++ ) { 2.143 + continue; 2.144 + } 2.145 ++ /* this cfg entry is '*' or matches username from peer */ 2.146 ++ *colon_after_user = '\0'; 2.147 ++ userinfo.name = user_and_passwd; 2.148 ++ userinfo.pw = colon_after_user + 1; 2.149 ++ r = pam_start("httpd", user_and_passwd, &conv_info, &pamh) != PAM_SUCCESS; 2.150 ++ if (r == 0) { 2.151 ++ r = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK) != PAM_SUCCESS 2.152 ++ || pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK) != PAM_SUCCESS 2.153 ++ ; 2.154 ++ pam_end(pamh, PAM_SUCCESS); 2.155 ++ } 2.156 ++ *colon_after_user = ':'; 2.157 ++ goto end_check_passwd; 2.158 ++# else 2.159 ++# if ENABLE_FEATURE_SHADOWPASSWDS 2.160 ++ /* Using _r function to avoid pulling in static buffers */ 2.161 ++ struct spwd spw; 2.162 ++# endif 2.163 ++ struct passwd *pw; 2.164 + 2.165 +- encrypted = pw_encrypt( 2.166 +- user_and_passwd + user_len_p1 /* cleartext pwd from user */, 2.167 +- md5_passwd /*salt */, 1 /* cleanup */); 2.168 +- r = strcmp(encrypted, md5_passwd); 2.169 +- free(encrypted); 2.170 +- if (r == 0) 2.171 +- goto set_remoteuser_var; /* Ok */ 2.172 ++ *colon_after_user = '\0'; 2.173 ++ pw = getpwnam(user_and_passwd); 2.174 ++ *colon_after_user = ':'; 2.175 ++ if (!pw || !pw->pw_passwd) 2.176 ++ continue; 2.177 ++ passwd = pw->pw_passwd; 2.178 ++# if ENABLE_FEATURE_SHADOWPASSWDS 2.179 ++ if ((passwd[0] == 'x' || passwd[0] == '*') && !passwd[1]) { 2.180 ++ /* getspnam_r may return 0 yet set result to NULL. 2.181 ++ * At least glibc 2.4 does this. Be extra paranoid here. */ 2.182 ++ struct spwd *result = NULL; 2.183 ++ r = getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result); 2.184 ++ if (r == 0 && result) 2.185 ++ passwd = result->sp_pwdp; /* note: passwd is located into buffer ! */ 2.186 ++ } 2.187 ++# endif 2.188 ++# endif /* ENABLE_PAM */ 2.189 ++ } 2.190 ++ 2.191 ++ /* compare "user:" */ 2.192 ++ if (cur->after_colon[0] != '*' 2.193 ++ && strncmp(cur->after_colon, user_and_passwd, colon_after_user - user_and_passwd + 1) != 0 2.194 ++ ) { 2.195 + continue; 2.196 + } 2.197 ++ /* this cfg entry is '*' or matches username from peer */ 2.198 ++ 2.199 ++ /* encrypt pwd from peer and check match with local one */ 2.200 ++ { 2.201 ++ char *encrypted = pw_encrypt( 2.202 ++ /* pwd: */ colon_after_user + 1, 2.203 ++ /* salt: */ passwd, 2.204 ++ /* cleanup: */ 0 2.205 ++ ); 2.206 ++ r = strcmp(encrypted, passwd); 2.207 ++ free(encrypted); 2.208 ++ goto end_check_passwd; 2.209 ++ } 2.210 ++ bad_input: ; 2.211 + } 2.212 + 2.213 + /* Comparing plaintext "user:pass" in one go */ 2.214 +- if (strcmp(cur->after_colon, user_and_passwd) == 0) { 2.215 +- set_remoteuser_var: 2.216 ++ end_check_passwd: 2.217 ++ r = strcmp(cur->after_colon, user_and_passwd); 2.218 ++ if (r == 0) { 2.219 + remoteuser = xstrndup(user_and_passwd, 2.220 + strchrnul(user_and_passwd, ':') - user_and_passwd); 2.221 + return 1; /* Ok */