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