wok-undigest rev 587
busybox/httpd: add support for system passwords (again)
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Thu Dec 01 22:35:18 2011 +0100 (2011-12-01) |
parents | 74db54588f46 |
children | 21d5de8c62e6 |
files | busybox/stuff/busybox-1.19-httpd.u |
line diff
1.1 --- a/busybox/stuff/busybox-1.19-httpd.u Thu Dec 01 12:33:10 2011 +0100 1.2 +++ b/busybox/stuff/busybox-1.19-httpd.u Thu Dec 01 22:35:18 2011 +0100 1.3 @@ -25,12 +25,12 @@ 1.4 #if ENABLE_FEATURE_HTTPD_USE_SENDFILE 1.5 # include <sys/sendfile.h> 1.6 #endif 1.7 -@@ -1730,6 +1740,57 @@ 1.8 +@@ -1730,6 +1740,56 @@ 1.9 } 1.10 1.11 #if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1.12 + 1.13 -+#if ENABLE_FEATURE_HTTPD_AUTH_MD5 && ENABLE_PAM 1.14 ++# if ENABLE_FEATURE_HTTPD_AUTH_MD5 && ENABLE_PAM 1.15 +struct pam_userinfo { 1.16 + const char *name; 1.17 + const char *pw; 1.18 @@ -49,9 +49,7 @@ 1.19 + return PAM_CONV_ERR; 1.20 + 1.21 + /* allocate memory to store response */ 1.22 -+ response = malloc(num_msg * sizeof(struct pam_response)); 1.23 -+ if (!response) 1.24 -+ return PAM_CONV_ERR; 1.25 ++ response = xzalloc(num_msg * sizeof(*response)); 1.26 + 1.27 + /* copy values */ 1.28 + for (i = 0; i < num_msg; i++) { 1.29 @@ -72,18 +70,28 @@ 1.30 + free(response); 1.31 + return PAM_CONV_ERR; 1.32 + } 1.33 -+ response[i].resp = strdup(s); 1.34 -+ response[i].resp_retcode = PAM_SUCCESS; 1.35 ++ response[i].resp = xstrdup(s); 1.36 ++ if (PAM_SUCCESS != 0) 1.37 ++ response[i].resp_retcode = PAM_SUCCESS; 1.38 + } 1.39 + *resp = response; 1.40 + return PAM_SUCCESS; 1.41 +} 1.42 -+#endif 1.43 ++# endif 1.44 + 1.45 /* 1.46 * Config file entries are of the form "/<path>:<user>:<passwd>". 1.47 * If config file has no prefix match for path, access is allowed. 1.48 -@@ -1747,6 +1808,7 @@ 1.49 +@@ -1739,7 +1799,7 @@ 1.50 + * 1.51 + * Returns 1 if user_and_passwd is OK. 1.52 + */ 1.53 +-static int check_user_passwd(const char *path, const char *user_and_passwd) 1.54 ++static int check_user_passwd(const char *path, char *user_and_passwd) 1.55 + { 1.56 + Htaccess *cur; 1.57 + const char *prev = NULL; 1.58 +@@ -1747,6 +1807,7 @@ 1.59 for (cur = g_auth; cur; cur = cur->next) { 1.60 const char *dir_prefix; 1.61 size_t len; 1.62 @@ -91,101 +99,129 @@ 1.63 1.64 dir_prefix = cur->before_colon; 1.65 1.66 -@@ -1771,36 +1833,80 @@ 1.67 +@@ -1771,36 +1832,96 @@ 1.68 prev = dir_prefix; 1.69 1.70 if (ENABLE_FEATURE_HTTPD_AUTH_MD5) { 1.71 - char *md5_passwd; 1.72 -+#if ENABLE_FEATURE_SHADOWPASSWDS && !ENABLE_PAM 1.73 -+ /* Using _r function to avoid pulling in static buffers */ 1.74 -+ struct spwd spw; 1.75 -+ char buffer[256]; 1.76 -+#endif 1.77 -+ const char *unencrypted = strchr(user_and_passwd, ':') + 1; 1.78 -+ const char *passwd = strchr(cur->after_colon, ':'); 1.79 -+ int user_len_p1 = unencrypted - user_and_passwd; 1.80 -+ char username[256]; 1.81 -+ 1.82 -+ strncpy(username, user_and_passwd, user_len_p1); 1.83 -+ username[user_len_p1 - 1] = 0; 1.84 -+ if (passwd && passwd[1] == '*') { 1.85 -+#if ENABLE_PAM 1.86 -+ struct pam_userinfo userinfo; 1.87 -+ struct pam_conv conv_info = {&pam_talker, (void *) &userinfo}; 1.88 -+ pam_handle_t *pamh; 1.89 -+ 1.90 -+ userinfo.name = username; 1.91 -+ userinfo.pw = unencrypted; 1.92 ++ char *colon_after_user; 1.93 ++ const char *passwd; 1.94 ++# if ENABLE_FEATURE_SHADOWPASSWDS && !ENABLE_PAM 1.95 ++ char sp_buf[256]; 1.96 ++# endif 1.97 1.98 - md5_passwd = strchr(cur->after_colon, ':'); 1.99 - if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1' 1.100 - && md5_passwd[3] == '$' && md5_passwd[4] 1.101 -+ if (cur->after_colon[0] != '*' && 1.102 -+ strncmp(username,cur->after_colon,user_len_p1 - 1) != 0) 1.103 -+ continue; 1.104 -+ r = pam_start("httpd", username, &conv_info, &pamh) != PAM_SUCCESS; 1.105 +- ) { 1.106 +- char *encrypted; 1.107 +- int r, user_len_p1; 1.108 ++ colon_after_user = strchr(user_and_passwd, ':'); 1.109 ++ if (!colon_after_user) 1.110 ++ goto bad_input; 1.111 ++ passwd = strchr(cur->after_colon, ':'); 1.112 ++ if (!passwd) 1.113 ++ goto bad_input; 1.114 ++ passwd++; 1.115 ++ if (passwd[0] == '*') { 1.116 ++# if ENABLE_PAM 1.117 ++ struct pam_userinfo userinfo; 1.118 ++ struct pam_conv conv_info = { &pam_talker, (void *) &userinfo }; 1.119 ++ pam_handle_t *pamh; 1.120 + 1.121 +- md5_passwd++; 1.122 +- user_len_p1 = md5_passwd - cur->after_colon; 1.123 +- /* comparing "user:" */ 1.124 +- if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) { 1.125 ++ /* compare "user:" */ 1.126 ++ if (cur->after_colon[0] != '*' 1.127 ++ && strncmp(cur->after_colon, user_and_passwd, colon_after_user - user_and_passwd + 1) != 0 1.128 ++ ) { 1.129 + continue; 1.130 + } 1.131 ++ /* this cfg entry is '*' or matches username from peer */ 1.132 ++ *colon_after_user = '\0'; 1.133 ++ userinfo.name = user_and_passwd; 1.134 ++ userinfo.pw = colon_after_user + 1; 1.135 ++ r = pam_start("httpd", user_and_passwd, &conv_info, &pamh) != PAM_SUCCESS; 1.136 + if (r == 0) { 1.137 + r = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK) != PAM_SUCCESS 1.138 -+ || pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK) != PAM_SUCCESS; 1.139 ++ || pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK) != PAM_SUCCESS 1.140 ++ ; 1.141 + pam_end(pamh, PAM_SUCCESS); 1.142 + } 1.143 ++ *colon_after_user = ':'; 1.144 + goto end_check_passwd; 1.145 -+#else 1.146 -+ struct passwd *pw = getpwnam(username); 1.147 ++# else 1.148 ++# if ENABLE_FEATURE_SHADOWPASSWDS 1.149 ++ /* Using _r function to avoid pulling in static buffers */ 1.150 ++ struct spwd spw; 1.151 ++# endif 1.152 ++ struct passwd *pw; 1.153 + 1.154 +- encrypted = pw_encrypt( 1.155 +- user_and_passwd + user_len_p1 /* cleartext pwd from user */, 1.156 +- md5_passwd /*salt */, 1 /* cleanup */); 1.157 +- r = strcmp(encrypted, md5_passwd); 1.158 +- free(encrypted); 1.159 +- if (r == 0) 1.160 +- goto set_remoteuser_var; /* Ok */ 1.161 ++ *colon_after_user = '\0'; 1.162 ++ pw = getpwnam(user_and_passwd); 1.163 ++ *colon_after_user = ':'; 1.164 + if (!pw || !pw->pw_passwd) 1.165 + continue; 1.166 + passwd = pw->pw_passwd; 1.167 -+#if ENABLE_FEATURE_SHADOWPASSWDS 1.168 ++# if ENABLE_FEATURE_SHADOWPASSWDS 1.169 + if ((passwd[0] == 'x' || passwd[0] == '*') && !passwd[1]) { 1.170 + /* getspnam_r may return 0 yet set result to NULL. 1.171 + * At least glibc 2.4 does this. Be extra paranoid here. */ 1.172 + struct spwd *result = NULL; 1.173 -+ r = getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result); 1.174 -+ if (!r && result) 1.175 ++ r = getspnam_r(pw->pw_name, &spw, sp_buf, sizeof(sp_buf), &result); 1.176 ++ if (r == 0 && result) 1.177 + passwd = result->sp_pwdp; 1.178 + } 1.179 -+#endif 1.180 -+ passwd--; 1.181 -+#endif // ENABLE_PAM 1.182 ++# endif 1.183 ++# endif /* ENABLE_PAM */ 1.184 + } 1.185 -+ if (passwd && passwd[1] == '$' && passwd[2] == '1' 1.186 -+ && passwd[3] == '$' && passwd[4] 1.187 - ) { 1.188 - char *encrypted; 1.189 -- int r, user_len_p1; 1.190 -- 1.191 -- md5_passwd++; 1.192 -- user_len_p1 = md5_passwd - cur->after_colon; 1.193 -+ 1.194 -+ passwd++; 1.195 - /* comparing "user:" */ 1.196 -- if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) { 1.197 -+ if (cur->after_colon[0] != '*' && 1.198 -+ strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) { 1.199 - continue; 1.200 - } 1.201 - 1.202 - encrypted = pw_encrypt( 1.203 -- user_and_passwd + user_len_p1 /* cleartext pwd from user */, 1.204 -- md5_passwd /*salt */, 1 /* cleanup */); 1.205 -- r = strcmp(encrypted, md5_passwd); 1.206 -+ unencrypted /* cleartext pwd from user */, 1.207 -+ passwd /*salt */, 1 /* cleanup */); 1.208 ++ 1.209 ++ /* compare "user:" */ 1.210 ++ if (cur->after_colon[0] != '*' 1.211 ++ && strncmp(cur->after_colon, user_and_passwd, colon_after_user - user_and_passwd + 1) != 0 1.212 ++ ) { 1.213 + continue; 1.214 + } 1.215 ++ /* this cfg entry is '*' or matches username from peer */ 1.216 ++ 1.217 ++ /* encrypt pwd from peer and check match with local one */ 1.218 ++ { 1.219 ++ char *encrypted = pw_encrypt( 1.220 ++ /* pwd: */ colon_after_user + 1, 1.221 ++ /* salt: */ passwd, 1.222 ++ /* cleanup: */ 0 1.223 ++ ); 1.224 + r = strcmp(encrypted, passwd); 1.225 - free(encrypted); 1.226 -- if (r == 0) 1.227 -- goto set_remoteuser_var; /* Ok */ 1.228 -- continue; 1.229 ++ free(encrypted); 1.230 + goto end_check_passwd; 1.231 - } 1.232 ++ } 1.233 ++ bad_input: ; 1.234 } 1.235 1.236 /* Comparing plaintext "user:pass" in one go */ 1.237 - if (strcmp(cur->after_colon, user_and_passwd) == 0) { 1.238 - set_remoteuser_var: 1.239 + r = strcmp(cur->after_colon, user_and_passwd); 1.240 -+end_check_passwd: 1.241 ++ end_check_passwd: 1.242 + if (r == 0) { 1.243 remoteuser = xstrndup(user_and_passwd, 1.244 strchrnul(user_and_passwd, ':') - user_and_passwd); 1.245 return 1; /* Ok */ 1.246 +@@ -2142,7 +2263,7 @@ 1.247 + /* Case: no "Authorization:" was seen, but page does require passwd. 1.248 + * Check that with dummy user:pass */ 1.249 + if (authorized < 0) 1.250 +- authorized = check_user_passwd(urlcopy, ":"); 1.251 ++ authorized = check_user_passwd(urlcopy, (char *) ""); 1.252 + if (!authorized) 1.253 + send_headers_and_exit(HTTP_UNAUTHORIZED); 1.254 + #endif