Release version 968 generated by do-release.sh
[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-2016 by the citadel.org team
5 //
6 // This program is open source software.  Use, duplication, and/or
7 // disclosure are subject to the GNU General Purpose License version 3.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13
14 #include "textclient.h"
15
16 #define PWFILENAME "%s/.citadel.passwords"
17
18 void determine_pwfilename(char *pwfile, size_t n) {
19         struct passwd *p;
20
21         p = getpwuid(getuid());
22         if (p == NULL)
23                 strcpy(pwfile, "");
24         snprintf(pwfile, n, PWFILENAME, p->pw_dir);
25 }
26
27
28 /*
29  * Check the password file for a host/port match; if found, stuff the user
30  * name and password into the user/pass buffers
31  */
32 void get_stored_password(char *host, char *port, char *username, char *password) {
33
34         char pwfile[PATH_MAX];
35         FILE *fp;
36         char buf[SIZ];
37         char buf64[SIZ];
38         char hostbuf[256], portbuf[256], ubuf[256], pbuf[256];
39
40         strcpy(username, "");
41         strcpy(password, "");
42
43         determine_pwfilename(pwfile, sizeof pwfile);
44         if (IsEmptyStr(pwfile))
45                 return;
46
47         fp = fopen(pwfile, "r");
48         if (fp == NULL)
49                 return;
50         while (fgets(buf64, sizeof buf64, fp) != NULL) {
51                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
52                 extract_token(hostbuf, buf, 0, '|', sizeof hostbuf);
53                 extract_token(portbuf, buf, 1, '|', sizeof portbuf);
54                 extract_token(ubuf, buf, 2, '|', sizeof ubuf);
55                 extract_token(pbuf, buf, 3, '|', sizeof pbuf);
56
57                 if (!strcasecmp(hostbuf, host)) {
58                         if (!strcasecmp(portbuf, port)) {
59                                 strcpy(username, ubuf);
60                                 strcpy(password, pbuf);
61                         }
62                 }
63         }
64         fclose(fp);
65 }
66
67
68 /*
69  * Set (or clear) stored passwords.
70  */
71 void set_stored_password(char *host, char *port, char *username, char *password) {
72
73         char pwfile[PATH_MAX];
74         FILE *fp, *oldfp;
75         char buf[SIZ];
76         char buf64[SIZ];
77         char hostbuf[256], portbuf[256], ubuf[256], pbuf[256];
78
79         determine_pwfilename(pwfile, sizeof pwfile);
80         if (IsEmptyStr(pwfile))
81                 return;
82
83         oldfp = fopen(pwfile, "r");
84         if (oldfp == NULL)
85                 oldfp = fopen("/dev/null", "r");
86         unlink(pwfile);
87         fp = fopen(pwfile, "w");
88         if (fp == NULL)
89                 fp = fopen("/dev/null", "w");
90         while (fgets(buf64, sizeof buf64, oldfp) != NULL) {
91                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
92                 extract_token(hostbuf, buf, 0, '|', sizeof hostbuf);
93                 extract_token(portbuf, buf, 1, '|', sizeof portbuf);
94                 extract_token(ubuf, buf, 2, '|', sizeof ubuf);
95                 extract_token(pbuf, buf, 3, '|', sizeof pbuf);
96
97                 if ((strcasecmp(hostbuf, host))
98                     || (strcasecmp(portbuf, port))) {
99                         snprintf(buf, sizeof buf, "%s|%s|%s|%s|", hostbuf, portbuf, ubuf, pbuf);
100                         CtdlEncodeBase64(buf64, buf, strlen(buf), BASE64_NO_LINEBREAKS);
101                         fprintf(fp, "%s\n", buf64);
102                 }
103         }
104         if (!IsEmptyStr(username)) {
105                 snprintf(buf, sizeof buf, "%s|%s|%s|%s|", host, port, username, password);
106                 CtdlEncodeBase64(buf64, buf, strlen(buf), BASE64_NO_LINEBREAKS);
107                 fprintf(fp, "%s\n", buf64);
108         }
109         fclose(oldfp);
110         fclose(fp);
111         chmod(pwfile, 0600);
112 }
113
114
115 /*
116  * Set the password if the user wants to, clear it otherwise 
117  */
118 void offer_to_remember_password(CtdlIPC * ipc, char *host, char *port, char *username, char *password) {
119
120         if (rc_remember_passwords) {
121                 if (boolprompt("Remember username/password for this site", 0)) {
122                         set_stored_password(host, port, username, password);
123                 }
124                 else {
125                         set_stored_password(host, port, "", "");
126                 }
127         }
128 }