/*
* $Id: client_passwords.c 5754 2007-11-16 05:52:26Z ajc $
*
* Functions which allow the client to remember usernames and passwords for
* various sites.
*
*/
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdio.h>
#include <libcitadel.h>
#include "citadel.h"
#include "citadel_ipc.h"
#include "commands.h"
#include "client_passwords.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), 0);
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), 0);
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, "", "");
}
}
}