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