3e864a41a3328d509e3d04b8258289202c86aa5d
[citadel.git] / textclient / src / client_passwords.c
1 /*
2  * Functions which allow the client to remember usernames and passwords for
3  * various sites.
4  *
5  * Copyright (c) 1987-2012 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 "sysdep.h"
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <pwd.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <libcitadel.h>
27 ///#include "citadel.h"
28 #include "citadel_ipc.h"
29 #include "commands.h"
30 #include "client_passwords.h"
31
32 #define PWFILENAME "%s/.citadel.passwords"
33
34 void determine_pwfilename(char *pwfile, size_t n) {
35         struct passwd *p;
36
37         p = getpwuid(getuid());
38         if (p == NULL) strcpy(pwfile, "");
39         snprintf(pwfile, n, PWFILENAME, p->pw_dir);
40 }
41
42
43 /*
44  * Check the password file for a host/port match; if found, stuff the user
45  * name and password into the user/pass buffers
46  */
47 void get_stored_password(
48                 char *host,
49                 char *port,
50                 char *username,
51                 char *password) {
52
53         char pwfile[PATH_MAX];
54         FILE *fp;
55         char buf[SIZ];
56         char buf64[SIZ];
57         char hostbuf[256], portbuf[256], ubuf[256], pbuf[256];
58
59         strcpy(username, "");
60         strcpy(password, "");
61
62         determine_pwfilename(pwfile, sizeof pwfile);
63         if (IsEmptyStr(pwfile)) return;
64
65         fp = fopen(pwfile, "r");
66         if (fp == NULL) return;
67         while (fgets(buf64, sizeof buf64, fp) != NULL) {
68                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
69                 extract_token(hostbuf, buf, 0, '|', sizeof hostbuf);
70                 extract_token(portbuf, buf, 1, '|', sizeof portbuf);
71                 extract_token(ubuf, buf, 2, '|', sizeof ubuf);
72                 extract_token(pbuf, buf, 3, '|', sizeof pbuf);
73
74                 if (!strcasecmp(hostbuf, host)) {
75                         if (!strcasecmp(portbuf, port)) {
76                                 strcpy(username, ubuf);
77                                 strcpy(password, pbuf);
78                         }
79                 }
80         }
81         fclose(fp);
82 }
83
84
85 /*
86  * Set (or clear) stored passwords.
87  */
88 void set_stored_password(
89                 char *host,
90                 char *port,
91                 char *username,
92                 char *password) {
93
94         char pwfile[PATH_MAX];
95         FILE *fp, *oldfp;
96         char buf[SIZ];
97         char buf64[SIZ];
98         char hostbuf[256], portbuf[256], ubuf[256], pbuf[256];
99
100         determine_pwfilename(pwfile, sizeof pwfile);
101         if (IsEmptyStr(pwfile)) return;
102
103         oldfp = fopen(pwfile, "r");
104         if (oldfp == NULL) oldfp = fopen("/dev/null", "r");
105         unlink(pwfile);
106         fp = fopen(pwfile, "w");
107         if (fp == NULL) fp = fopen("/dev/null", "w");
108         while (fgets(buf64, sizeof buf64, oldfp) != NULL) {
109                 CtdlDecodeBase64(buf, buf64, sizeof(buf64));
110                 extract_token(hostbuf, buf, 0, '|', sizeof hostbuf);
111                 extract_token(portbuf, buf, 1, '|', sizeof portbuf);
112                 extract_token(ubuf, buf, 2, '|', sizeof ubuf);
113                 extract_token(pbuf, buf, 3, '|', sizeof pbuf);
114
115                 if ( (strcasecmp(hostbuf, host)) 
116                    || (strcasecmp(portbuf, port)) ) {
117                         snprintf(buf, sizeof buf, "%s|%s|%s|%s|",
118                                 hostbuf, portbuf, ubuf, pbuf);
119                         CtdlEncodeBase64(buf64, buf, strlen(buf), 0);
120                         fprintf(fp, "%s\n", buf64);
121                 }
122         }
123         if (!IsEmptyStr(username)) {
124                 snprintf(buf, sizeof buf, "%s|%s|%s|%s|",
125                         host, port, username, password);
126                 CtdlEncodeBase64(buf64, buf, strlen(buf), 0);
127                 fprintf(fp, "%s\n", buf64);
128         }
129         fclose(oldfp);
130         fclose(fp);
131         chmod(pwfile, 0600);
132 }
133
134
135 /*
136  * Set the password if the user wants to, clear it otherwise 
137  */
138 void offer_to_remember_password(CtdlIPC *ipc,
139                 char *host,
140                 char *port,
141                 char *username,
142                 char *password) {
143
144         if (rc_remember_passwords) {
145                 if (boolprompt("Remember username/password for this site", 0)) {
146                         set_stored_password(host, port, username, password);
147                 }
148                 else {
149                         set_stored_password(host, port, "", "");
150                 }
151         }
152 }