stringbuf.c: random idle style cleanup.
[citadel.git] / textclient / client_passwords.c
1 // Functions which allow the client to remember usernames and passwords for various sites.
2 //
3 // Copyright (c) 1987-2023 by the citadel.org team
4 //
5 // This program is open source software.  Use, duplication, or disclosure is subject to the GNU General Public License version 3.
6
7 #include "textclient.h"
8
9 #define PWFILENAME "%s/.citadel.passwords"
10
11 void determine_pwfilename(char *pwfile, size_t n) {
12         struct passwd *p;
13
14         p = getpwuid(getuid());
15         if (p == NULL)
16                 strcpy(pwfile, "");
17         snprintf(pwfile, n, PWFILENAME, p->pw_dir);
18 }
19
20
21 // Check the password file for a host/port match; if found, stuff the user
22 // name and password into the user/pass buffers
23 void get_stored_password(char *host, char *port, char *username, char *password) {
24
25         char pwfile[PATH_MAX];
26         FILE *fp;
27         char buf[SIZ];
28         char buf64[SIZ];
29         char hostbuf[256], portbuf[256], ubuf[256], pbuf[256];
30
31         strcpy(username, "");
32         strcpy(password, "");
33
34         determine_pwfilename(pwfile, sizeof pwfile);
35         if (IsEmptyStr(pwfile))
36                 return;
37
38         fp = fopen(pwfile, "r");
39         if (fp == NULL) {
40                 return;
41         }
42         while (fgets(buf64, sizeof buf64, fp) != NULL) {
43                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
44                 extract_token(hostbuf, buf, 0, '|', sizeof hostbuf);
45                 extract_token(portbuf, buf, 1, '|', sizeof portbuf);
46                 extract_token(ubuf, buf, 2, '|', sizeof ubuf);
47                 extract_token(pbuf, buf, 3, '|', sizeof pbuf);
48
49                 if (!strcasecmp(hostbuf, host)) {
50                         if (!strcasecmp(portbuf, port)) {
51                                 strcpy(username, ubuf);
52                                 strcpy(password, pbuf);
53                         }
54                 }
55         }
56         fclose(fp);
57 }
58
59
60 // Set (or clear) stored passwords.
61 void set_stored_password(char *host, char *port, char *username, char *password) {
62
63         char pwfile[PATH_MAX];
64         FILE *fp, *oldfp;
65         char buf[SIZ];
66         char buf64[SIZ];
67         char hostbuf[256], portbuf[256], ubuf[256], pbuf[256];
68
69         determine_pwfilename(pwfile, sizeof pwfile);
70         if (IsEmptyStr(pwfile))
71                 return;
72
73         oldfp = fopen(pwfile, "r");
74         if (oldfp == NULL) {
75                 oldfp = fopen("/dev/null", "r");
76         }
77         unlink(pwfile);
78         fp = fopen(pwfile, "w");
79         if (fp == NULL) {
80                 fp = fopen("/dev/null", "w");
81         }
82         while (fgets(buf64, sizeof buf64, oldfp) != NULL) {
83                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
84                 extract_token(hostbuf, buf, 0, '|', sizeof hostbuf);
85                 extract_token(portbuf, buf, 1, '|', sizeof portbuf);
86                 extract_token(ubuf, buf, 2, '|', sizeof ubuf);
87                 extract_token(pbuf, buf, 3, '|', sizeof pbuf);
88
89                 if ((strcasecmp(hostbuf, host)) || (strcasecmp(portbuf, port))) {
90                         snprintf(buf, sizeof buf, "%s|%s|%s|%s|", hostbuf, portbuf, ubuf, pbuf);
91                         CtdlEncodeBase64(buf64, buf, strlen(buf), BASE64_NO_LINEBREAKS);
92                         fprintf(fp, "%s\n", buf64);
93                 }
94         }
95         if (!IsEmptyStr(username)) {
96                 snprintf(buf, sizeof buf, "%s|%s|%s|%s|", host, port, username, password);
97                 CtdlEncodeBase64(buf64, buf, strlen(buf), BASE64_NO_LINEBREAKS);
98                 fprintf(fp, "%s\n", buf64);
99         }
100         fclose(oldfp);
101         fclose(fp);
102         chmod(pwfile, 0600);
103 }
104
105
106 // Set the password if the user wants to, clear it otherwise 
107 void offer_to_remember_password(CtdlIPC * ipc, char *host, char *port, char *username, char *password) {
108
109         if (rc_remember_passwords) {
110                 if (boolprompt("Remember username/password for this site", 0)) {
111                         set_stored_password(host, port, username, password);
112                 }
113                 else {
114                         set_stored_password(host, port, "", "");
115                 }
116         }
117 }