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