* Holy war on strlen: use IsEmptyStr where apropriate.
[citadel.git] / citadel / client_passwords.c
1 /*
2  * $Id$
3  *
4  * Functions which allow the client to remember usernames and passwords for
5  * various sites.
6  *
7  */
8
9 #include "sysdep.h"
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <pwd.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <limits.h>
18 #include <stdio.h>
19 #include "citadel.h"
20 #include "citadel_ipc.h"
21 #include "tools.h"
22 #include "commands.h"
23 #include "client_passwords.h"
24
25 #define PWFILENAME "%s/.citadel.passwords"
26
27 void determine_pwfilename(char *pwfile, size_t n) {
28         struct passwd *p;
29
30         p = getpwuid(getuid());
31         if (p == NULL) strcpy(pwfile, "");
32         snprintf(pwfile, n, PWFILENAME, p->pw_dir);
33 }
34
35
36 /*
37  * Check the password file for a host/port match; if found, stuff the user
38  * name and password into the user/pass buffers
39  */
40 void get_stored_password(
41                 char *host,
42                 char *port,
43                 char *username,
44                 char *password) {
45
46         char pwfile[PATH_MAX];
47         FILE *fp;
48         char buf[SIZ];
49         char buf64[SIZ];
50         char hostbuf[256], portbuf[256], ubuf[256], pbuf[256];
51
52         strcpy(username, "");
53         strcpy(password, "");
54
55         determine_pwfilename(pwfile, sizeof pwfile);
56         if (IsEmptyStr(pwfile)) return;
57
58         fp = fopen(pwfile, "r");
59         if (fp == NULL) return;
60         while (fgets(buf64, sizeof buf64, fp) != NULL) {
61                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
62                 extract_token(hostbuf, buf, 0, '|', sizeof hostbuf);
63                 extract_token(portbuf, buf, 1, '|', sizeof portbuf);
64                 extract_token(ubuf, buf, 2, '|', sizeof ubuf);
65                 extract_token(pbuf, buf, 3, '|', sizeof pbuf);
66
67                 if (!strcasecmp(hostbuf, host)) {
68                         if (!strcasecmp(portbuf, port)) {
69                                 strcpy(username, ubuf);
70                                 strcpy(password, pbuf);
71                         }
72                 }
73         }
74         fclose(fp);
75 }
76
77
78 /*
79  * Set (or clear) stored passwords.
80  */
81 void set_stored_password(
82                 char *host,
83                 char *port,
84                 char *username,
85                 char *password) {
86
87         char pwfile[PATH_MAX];
88         FILE *fp, *oldfp;
89         char buf[SIZ];
90         char buf64[SIZ];
91         char hostbuf[256], portbuf[256], ubuf[256], pbuf[256];
92
93         determine_pwfilename(pwfile, sizeof pwfile);
94         if (IsEmptyStr(pwfile)) return;
95
96         oldfp = fopen(pwfile, "r");
97         if (oldfp == NULL) oldfp = fopen("/dev/null", "r");
98         unlink(pwfile);
99         fp = fopen(pwfile, "w");
100         if (fp == NULL) fp = fopen("/dev/null", "w");
101         while (fgets(buf64, sizeof buf64, oldfp) != NULL) {
102                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
103                 extract_token(hostbuf, buf, 0, '|', sizeof hostbuf);
104                 extract_token(portbuf, buf, 1, '|', sizeof portbuf);
105                 extract_token(ubuf, buf, 2, '|', sizeof ubuf);
106                 extract_token(pbuf, buf, 3, '|', sizeof pbuf);
107
108                 if ( (strcasecmp(hostbuf, host)) 
109                    || (strcasecmp(portbuf, port)) ) {
110                         snprintf(buf, sizeof buf, "%s|%s|%s|%s|",
111                                 hostbuf, portbuf, ubuf, pbuf);
112                         CtdlEncodeBase64(buf64, buf, strlen(buf));
113                         fprintf(fp, "%s\n", buf64);
114                 }
115         }
116         if (!IsEmptyStr(username)) {
117                 snprintf(buf, sizeof buf, "%s|%s|%s|%s|",
118                         host, port, username, password);
119                 CtdlEncodeBase64(buf64, buf, strlen(buf));
120                 fprintf(fp, "%s\n", buf64);
121         }
122         fclose(oldfp);
123         fclose(fp);
124         chmod(pwfile, 0600);
125 }
126
127
128 /*
129  * Set the password if the user wants to, clear it otherwise 
130  */
131 void offer_to_remember_password(CtdlIPC *ipc,
132                 char *host,
133                 char *port,
134                 char *username,
135                 char *password) {
136
137         if (rc_remember_passwords) {
138                 if (boolprompt("Remember username/password for this site", 0)) {
139                         set_stored_password(host, port, username, password);
140                 }
141                 else {
142                         set_stored_password(host, port, "", "");
143                 }
144         }
145 }