* Allow multiple simultaneous IPC connections. All changes necessary for
[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
24 #define PWFILENAME "%s/.citadel.passwords"
25
26 static void determine_pwfilename(char *pwfile, size_t n) {
27         struct passwd *p;
28
29         p = getpwuid(getuid());
30         if (p == NULL) strcpy(pwfile, "");
31         snprintf(pwfile, n, PWFILENAME, p->pw_dir);
32 }
33
34
35 /*
36  * Check the password file for a host/port match; if found, stuff the user
37  * name and password into the user/pass buffers
38  */
39 void get_stored_password(
40                 char *host,
41                 char *port,
42                 char *username,
43                 char *password) {
44
45         char pwfile[PATH_MAX];
46         FILE *fp;
47         char buf[SIZ];
48         char buf64[SIZ];
49         char hostbuf[SIZ], portbuf[SIZ], ubuf[SIZ], pbuf[SIZ];
50
51         strcpy(username, "");
52         strcpy(password, "");
53
54         determine_pwfilename(pwfile, sizeof pwfile);
55         if (strlen(pwfile)==0) return;
56
57         fp = fopen(pwfile, "r");
58         if (fp == NULL) return;
59         while (fgets(buf64, sizeof buf64, fp) != NULL) {
60                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
61                 extract(hostbuf, buf, 0);
62                 extract(portbuf, buf, 1);
63                 extract(ubuf, buf, 2);
64                 extract(pbuf, buf, 3);
65
66                 if (!strcasecmp(hostbuf, host)) {
67                         if (!strcasecmp(portbuf, port)) {
68                                 strcpy(username, ubuf);
69                                 strcpy(password, pbuf);
70                         }
71                 }
72         }
73         fclose(fp);
74 }
75
76
77 /*
78  * Set (or clear) stored passwords.
79  */
80 void set_stored_password(
81                 char *host,
82                 char *port,
83                 char *username,
84                 char *password) {
85
86         char pwfile[PATH_MAX];
87         FILE *fp, *oldfp;
88         char buf[SIZ];
89         char buf64[SIZ];
90         char hostbuf[SIZ], portbuf[SIZ], ubuf[SIZ], pbuf[SIZ];
91
92         determine_pwfilename(pwfile, sizeof pwfile);
93         if (strlen(pwfile)==0) return;
94
95         oldfp = fopen(pwfile, "r");
96         if (oldfp == NULL) oldfp = fopen("/dev/null", "r");
97         unlink(pwfile);
98         fp = fopen(pwfile, "w");
99         if (fp == NULL) fp = fopen("/dev/null", "w");
100         while (fgets(buf64, sizeof buf64, oldfp) != NULL) {
101                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
102                 extract(hostbuf, buf, 0);
103                 extract(portbuf, buf, 1);
104                 extract(ubuf, buf, 2);
105                 extract(pbuf, buf, 3);
106
107                 if ( (strcasecmp(hostbuf, host)) 
108                    || (strcasecmp(portbuf, port)) ) {
109                         snprintf(buf, sizeof buf, "%s|%s|%s|%s|",
110                                 hostbuf, portbuf, ubuf, pbuf);
111                         encode_base64(buf64, buf);
112                         fprintf(fp, "%s\n", buf64);
113                 }
114         }
115         if (strlen(username) > 0) {
116                 snprintf(buf, sizeof buf, "%s|%s|%s|%s|",
117                         host, port, username, password);
118                 encode_base64(buf64, buf);
119                 fprintf(fp, "%s\n", buf64);
120         }
121         fclose(oldfp);
122         fclose(fp);
123         chmod(pwfile, 0600);
124 }
125
126
127 /*
128  * Set the password if the user wants to, clear it otherwise 
129  */
130 void offer_to_remember_password(CtdlIPC *ipc,
131                 char *host,
132                 char *port,
133                 char *username,
134                 char *password) {
135
136         if (rc_remember_passwords) {
137                 if (boolprompt("Remember username/password for this site", 0)) {
138                         set_stored_password(host, port, username, password);
139                 }
140                 else {
141                         set_stored_password(host, port, "", "");
142                 }
143         }
144 }