// Functions which allow the client to remember usernames and passwords for // various sites. // // Copyright (c) 1987-2016 by the citadel.org team // // This program is open source software. Use, duplication, and/or // disclosure are subject to the GNU General Purpose License version 3. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. #include "textclient.h" #define PWFILENAME "%s/.citadel.passwords" void determine_pwfilename(char *pwfile, size_t n) { struct passwd *p; p = getpwuid(getuid()); if (p == NULL) strcpy(pwfile, ""); snprintf(pwfile, n, PWFILENAME, p->pw_dir); } /* * Check the password file for a host/port match; if found, stuff the user * name and password into the user/pass buffers */ void get_stored_password(char *host, char *port, char *username, char *password) { char pwfile[PATH_MAX]; FILE *fp; char buf[SIZ]; char buf64[SIZ]; char hostbuf[256], portbuf[256], ubuf[256], pbuf[256]; strcpy(username, ""); strcpy(password, ""); determine_pwfilename(pwfile, sizeof pwfile); if (IsEmptyStr(pwfile)) return; fp = fopen(pwfile, "r"); if (fp == NULL) return; while (fgets(buf64, sizeof buf64, fp) != NULL) { CtdlDecodeBase64(buf, buf64, sizeof(buf64)); extract_token(hostbuf, buf, 0, '|', sizeof hostbuf); extract_token(portbuf, buf, 1, '|', sizeof portbuf); extract_token(ubuf, buf, 2, '|', sizeof ubuf); extract_token(pbuf, buf, 3, '|', sizeof pbuf); if (!strcasecmp(hostbuf, host)) { if (!strcasecmp(portbuf, port)) { strcpy(username, ubuf); strcpy(password, pbuf); } } } fclose(fp); } /* * Set (or clear) stored passwords. */ void set_stored_password(char *host, char *port, char *username, char *password) { char pwfile[PATH_MAX]; FILE *fp, *oldfp; char buf[SIZ]; char buf64[SIZ]; char hostbuf[256], portbuf[256], ubuf[256], pbuf[256]; determine_pwfilename(pwfile, sizeof pwfile); if (IsEmptyStr(pwfile)) return; oldfp = fopen(pwfile, "r"); if (oldfp == NULL) oldfp = fopen("/dev/null", "r"); unlink(pwfile); fp = fopen(pwfile, "w"); if (fp == NULL) fp = fopen("/dev/null", "w"); while (fgets(buf64, sizeof buf64, oldfp) != NULL) { CtdlDecodeBase64(buf, buf64, sizeof(buf64)); extract_token(hostbuf, buf, 0, '|', sizeof hostbuf); extract_token(portbuf, buf, 1, '|', sizeof portbuf); extract_token(ubuf, buf, 2, '|', sizeof ubuf); extract_token(pbuf, buf, 3, '|', sizeof pbuf); if ((strcasecmp(hostbuf, host)) || (strcasecmp(portbuf, port))) { snprintf(buf, sizeof buf, "%s|%s|%s|%s|", hostbuf, portbuf, ubuf, pbuf); CtdlEncodeBase64(buf64, buf, strlen(buf), BASE64_NO_LINEBREAKS); fprintf(fp, "%s\n", buf64); } } if (!IsEmptyStr(username)) { snprintf(buf, sizeof buf, "%s|%s|%s|%s|", host, port, username, password); CtdlEncodeBase64(buf64, buf, strlen(buf), BASE64_NO_LINEBREAKS); fprintf(fp, "%s\n", buf64); } fclose(oldfp); fclose(fp); chmod(pwfile, 0600); } /* * Set the password if the user wants to, clear it otherwise */ void offer_to_remember_password(CtdlIPC * ipc, char *host, char *port, char *username, char *password) { if (rc_remember_passwords) { if (boolprompt("Remember username/password for this site", 0)) { set_stored_password(host, port, username, password); } else { set_stored_password(host, port, "", ""); } } }