diff options
Diffstat (limited to 'etc.c')
-rw-r--r-- | etc.c | 188 |
1 files changed, 185 insertions, 3 deletions
@@ -1,4 +1,4 @@ -/* $Id: etc.c,v 1.22 2002/06/07 15:46:44 ukai Exp $ */ +/* $Id: etc.c,v 1.23 2002/09/24 16:35:02 ukai Exp $ */ #include "fm.h" #include <pwd.h> #include "myctype.h" @@ -24,6 +24,18 @@ #define close(x) close_s(x) #endif /* __WATT32__ */ +struct auth_pass { + int is_proxy; + Str host; + int port; + Str file; + Str realm; + Str uname; + Str pwd; + struct auth_pass *next; +}; + +struct auth_pass *passwords = NULL; int columnSkip(Buffer *buf, int offset) @@ -838,6 +850,150 @@ correct_irrtag(int status) return tmp; } +static int +dir_under(const char *x, const char *y) +{ + size_t len = strlen(x); + return x[len - 1] == '/' + && strlen(y) >= len + && y[len - 1] == '/' && strncasecmp(x, y, len) == 0; +} + +static void +add_auth_pass_entry(const struct auth_pass *ent) +{ + if (ent->host && (ent->is_proxy || ent->file || ent->realm) + && ent->uname && ent->pwd) { + struct auth_pass *newent = New(struct auth_pass); + memcpy(newent, ent, sizeof(struct auth_pass)); + newent->next = passwords; + passwords = newent; + } + /* ignore invalid entries */ +} + +static struct auth_pass * +find_auth_pass_entry(char *host, int port, char *file, char *realm, + int is_proxy) +{ + struct auth_pass *ent; + for (ent = passwords; ent != NULL; ent = ent->next) { + if (ent->is_proxy == is_proxy && !Strcmp_charp(ent->host, host) + && (!ent->port || ent->port == port) + && (!ent->file || !file || dir_under(ent->file->ptr, file)) + && (!ent->realm || !realm || !Strcmp_charp(ent->realm, realm)) + ) + return ent; + } + return NULL; +} + +int +find_auth_user_passwd(char *host, int port, char *file, char *realm, + Str *uname, Str *pwd, int is_proxy) +{ + struct auth_pass *ent; + ent = find_auth_pass_entry(host, port, file, realm, is_proxy); + if (ent) { + *uname = ent->uname; + *pwd = ent->pwd; + return 1; + } + return 0; +} + +/* passwd */ +/* + * machine <name> + * port <port> + * proxy + * path <file> + * realm <realm> + * login <login> + * passwd <passwd> + */ + +#define PASS_IS_READABLE_MSG "SECURITY NOTE: password file must not be accessible by others" +void +loadPasswd(void) +{ + struct stat st; + FILE *fp; + struct auth_pass ent; + + if (passwd_file == NULL) + return; + if (stat(expandName(passwd_file), &st) < 0) + return; + + /* check permissions, if group or others readable or writable, + * refuse it, because it's insecure. + */ + if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + if (fmInitialized) { + message(PASS_IS_READABLE_MSG, 0, 0); + refresh(); + } + else { + fputs(PASS_IS_READABLE_MSG, stderr); + fputc('\n', stderr); + } + sleep(2); + return; + } + + fp = fopen(expandName(passwd_file), "r"); + if (fp == NULL) + return; /* never? */ + + bzero(&ent, sizeof(struct auth_pass)); + while (1) { + Str line; + Str arg = NULL; + char *p, *q; + + line = Strfgets(fp); + if (line->length == 0) + break; + p = line->ptr; + p[line->length - 1] = '\0'; /* remove CR */ + SKIP_BLANKS(p); + + if (*p == '#' || *p == '\0') + continue; /* comment or empty line */ + q = p; + SKIP_NON_BLANKS(q); + if (*q != '\0') { + *q++ = '\0'; + SKIP_BLANKS(q); + if (*q != '\0') + arg = Strnew_charp(q); + } + + if (!strcmp(p, "machine")) { + add_auth_pass_entry(&ent); + bzero(&ent, sizeof(struct auth_pass)); + ent.host = arg; + } + else if (!strcmp(p, "port") && arg) + ent.port = atoi(arg->ptr); + else if (!strcmp(p, "proxy") && !arg) + ent.is_proxy = 1; + else if (!strcmp(p, "path")) + ent.file = arg; + else if (!strcmp(p, "realm")) + ent.realm = arg; + else if (!strcmp(p, "login")) + ent.uname = arg; + else if (!strcmp(p, "password")) + ent.pwd = arg; + /* ignore */ + } + add_auth_pass_entry(&ent); + fclose(fp); + return; +} + /* authentication */ struct auth_cookie * find_auth(char *host, int port, char *file, char *realm) @@ -848,7 +1004,7 @@ find_auth(char *host, int port, char *file, char *realm) if (!Strcasecmp_charp(p->host, host) && p->port == port && ((realm && !Strcasecmp_charp(p->realm, realm)) || - (p->file && file && !Strcasecmp_charp(p->file, file)))) + (p->file && file && dir_under(p->file->ptr, file)))) return p; } return NULL; @@ -863,16 +1019,39 @@ find_auth_cookie(char *host, int port, char *file, char *realm) return NULL; } +#ifdef AUTH_DEBUG +static void +dump_auth_cookie(void) +{ + if (w3m_debug) { + FILE *ff = fopen("zzzauth", "a"); + struct auth_cookie *p; + + for (p = Auth_cookie; p != NULL; p = p->next) { + Str tmp = Sprintf("%s, %d, %s, %s\n", p->host->ptr, p->port, + p->file ? (const char *)p->file->ptr : "NULL", + p->realm ? (const char *)p->realm->ptr : "NULL"); + fwrite(tmp->ptr, sizeof(char), tmp->length, ff); + } + fputc('\n', ff); + fclose(ff); + } +} +#endif + void add_auth_cookie(char *host, int port, char *file, char *realm, Str cookie) { struct auth_cookie *p; p = find_auth(host, port, file, realm); - if (p) { + if (p && (!p->file || !Strcasecmp_charp(p->file, file))) { if (realm && p->realm == NULL) p->realm = Strnew_charp(realm); p->cookie = cookie; +#ifdef AUTH_DEBUG + dump_auth_cookie(); +#endif return; } p = New(struct auth_cookie); @@ -883,6 +1062,9 @@ add_auth_cookie(char *host, int port, char *file, char *realm, Str cookie) p->cookie = cookie; p->next = Auth_cookie; Auth_cookie = p; +#ifdef AUTH_DEBUG + dump_auth_cookie(); +#endif } /* get last modified time */ |