2 * Client authentication functions
18 #include "httpp/httpp.h"
22 #define CATMODULE "auth"
24 auth_result
auth_check_client(source_t
*source
, client_t
*client
)
26 auth_t
*authenticator
= source
->authenticator
;
29 /* This will look something like "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" */
30 char *header
= httpp_getvar(client
->parser
, "authorization");
32 char *username
, *password
;
37 if(strncmp(header
, "Basic ", 6)) {
38 INFO0("Authorization not using Basic");
42 userpass
= util_base64_decode(header
+6);
43 if(userpass
== NULL
) {
44 WARN1("Base64 decode of Authorization header \"%s\" failed",
49 tmp
= strchr(userpass
, ':');
59 auth_result result
= authenticator
->authenticate(
60 authenticator
, username
, password
);
63 client
->username
= strdup(username
);
73 static auth_t
*auth_get_htpasswd_auth(config_options_t
*options
);
75 auth_t
*auth_get_authenticator(char *type
, config_options_t
*options
)
78 if(!strcmp(type
, "htpasswd")) {
79 auth
= auth_get_htpasswd_auth(options
);
82 ERROR1("Unrecognised authenticator type: \"%s\"", type
);
87 ERROR1("Couldn't configure authenticator of type \"%s\"", type
);
94 } htpasswd_auth_state
;
96 static void htpasswd_clear(auth_t
*self
) {
97 htpasswd_auth_state
*state
= self
->state
;
98 free(state
->filename
);
103 static int get_line(FILE *file
, char *buf
, int len
)
105 if(fgets(buf
, len
, file
)) {
106 int len
= strlen(buf
);
107 if(len
> 0 && buf
[len
-1] == '\n') {
109 if(len
> 0 && buf
[len
-1] == '\r')
118 static char *get_hash(char *data
, int len
)
120 struct MD5Context context
;
124 MD5Update(&context
, data
, len
);
126 unsigned char digest
[16];
127 MD5Final(digest
, &context
);
129 return util_bin_to_hex(digest
, 16);
132 #define MAX_LINE_LEN 512
134 /* Not efficient; opens and scans the entire file for every request */
135 static auth_result
htpasswd_auth(auth_t
*auth
, char *username
, char *password
)
137 htpasswd_auth_state
*state
= auth
->state
;
138 FILE *passwdfile
= fopen(state
->filename
, "rb");
139 char line
[MAX_LINE_LEN
];
142 if(passwdfile
== NULL
) {
143 WARN2("Failed to open authentication database \"%s\": %s",
144 state
->filename
, strerror(errno
));
148 while(get_line(passwdfile
, line
, MAX_LINE_LEN
)) {
149 if(!line
[0] || line
[0] == '#')
152 sep
= strchr(line
, ':');
154 DEBUG0("No seperator in line");
159 if(!strcmp(username
, line
)) {
160 /* Found our user, now: does the hash of password match hash? */
162 char *hashed_password
= get_hash(password
, strlen(password
));
163 if(!strcmp(hash
, hashed_password
)) {
165 free(hashed_password
);
168 free(hashed_password
);
169 /* We don't keep searching through the file */
179 static auth_t
*auth_get_htpasswd_auth(config_options_t
*options
)
181 auth_t
*authenticator
= calloc(1, sizeof(auth_t
));
183 authenticator
->authenticate
= htpasswd_auth
;
184 authenticator
->free
= htpasswd_clear
;
186 htpasswd_auth_state
*state
= calloc(1, sizeof(htpasswd_auth_state
));
189 if(!strcmp(options
->name
, "filename"))
190 state
->filename
= strdup(options
->value
);
191 options
= options
->next
;
194 if(!state
->filename
) {
197 ERROR0("No filename given in options for authenticator.");
201 authenticator
->state
= state
;
202 DEBUG1("Configured htpasswd authentication using password file %s",
205 return authenticator
;