--- smbpwman-0.5.orig/smbpw.h 2004-09-22 12:01:55.000000000 +1000 +++ smbpwman-0.5.orig/smbpw.h 2004-09-22 12:17:48.000000000 +1000 @@ -33,21 +33,27 @@ #define SERVER_PATH "/usr/sbin/" #endif +// Maximum time in seconds to cache credentials +#ifndef MAX_CACHE_AGE +#define MAX_CACHE_AGE 5 +#endif + // The following comes from unix(7) #define UNIX_PATH_MAX 108 // internal helpers -int verify_socket_path(char *name); -int open_unix_socket(char *name); -char *readstring(int cs); -int unix_connect(char *name); +int smbpw_verify_socket_path(char *name); +int smbpw_open_unix_socket(char *name); +char *smbpw_readstring(int cs); +int smbpw_unix_connect(char *name); // external interface -int store(char *username, char *password); -char *retrieve(char *username); -int shutdown_server(void); +int smbpw_store(char *username, char *password); +char *smbpw_retrieve(char *username); +int smbpw_shutdown_server(void); +void smbpw_flush(int flushall); #ifdef DEBUG -void dump(void); +void smbpw_dump(void); #endif /* DEBUG */ #endif --- smbpwman-0.5.orig/smbpwcommon.c 2004-09-22 12:20:21.000000000 +1000 +++ smbpwman-0.5.orig/smbpwcommon.c 2004-09-22 12:17:48.000000000 +1000 @@ -17,7 +17,7 @@ * funny buggers with the socket and subvert the security. * */ -int verify_socket_path(char *name) +int smbpw_verify_socket_path(char *name) { int i = 0; char x; @@ -68,7 +68,7 @@ return result; } -int open_unix_socket(char *name) +int smbpw_open_unix_socket(char *name) { struct stat stat_buf; int ss; @@ -119,7 +119,7 @@ return ss; } -int unix_connect(char *name) +int smbpw_unix_connect(char *name) { struct sockaddr_un addr; int cs = socket(PF_UNIX, SOCK_STREAM, 0); @@ -141,7 +141,7 @@ return cs; } -char *readstring(int cs) +char *smbpw_readstring(int cs) { char buffer[1024]; int i = 0; @@ -166,7 +166,7 @@ return strdup(buffer); } -int store(char *username, char *password) +int smbpw_store(char *username, char *password) { int cs; char command; @@ -176,7 +176,7 @@ int delay = 1; - cs = unix_connect(SOCKET_NAME); + cs = smbpw_unix_connect(SOCKET_NAME); if(cs < 0) { while(attempts > 0) @@ -185,7 +185,7 @@ sleep(delay); delay = delay * 2; - cs = unix_connect(SOCKET_NAME); + cs = smbpw_unix_connect(SOCKET_NAME); if(cs >= 0) { break; @@ -223,20 +223,32 @@ return 0; } -#ifdef DEBUG -void dump(void) +void writecommand(char command) { int cs; - char command = 0x03; - cs = unix_connect(SOCKET_NAME); + cs = smbpw_unix_connect(SOCKET_NAME); write(cs, &command, sizeof(command)); close(cs); } + +void smbpw_flush(int flushall) +{ + if (flushall) + writecommand(0x05); + else + writecommand(0x04); +} + +#ifdef DEBUG +void smbpw_dump(void) +{ + writecommand(0x03); +} #endif /* DEBUG */ -char *retrieve(char *username) +char *smbpw_retrieve(char *username) { int cs; char command; @@ -244,11 +256,11 @@ char result = 0xff; char *password = 0; - cs = unix_connect(SOCKET_NAME); + cs = smbpw_unix_connect(SOCKET_NAME); if(cs < 0) { - cs = unix_connect(SOCKET_NAME); + cs = smbpw_unix_connect(SOCKET_NAME); } // retrieve @@ -263,7 +275,7 @@ if(result == 0x00) { - password = readstring(cs); + password = smbpw_readstring(cs); //printf("The password is %s\n", password); } } @@ -281,13 +293,13 @@ return password; } -int shutdown_server(void) +int smbpw_shutdown_server(void) { int cs; char command; char result = 0x00; - cs = unix_connect(SOCKET_NAME); + cs = smbpw_unix_connect(SOCKET_NAME); // store command = 0x02; --- smbpwman-0.5.orig/smbpwman.c 2004-09-22 12:01:55.000000000 +1000 +++ smbpwman-0.5.orig/smbpwman.c 2004-09-22 12:17:48.000000000 +1000 @@ -39,6 +39,10 @@ * * all str commands are 0x00 terminated string of chars. * + * Patched by Chris Jensen - 22 Sep 2004 + * Expire cached passwords after short timeout + * Add flush and flushall requests + * Rename shared functions to avoid naming collisions * Patched by Chris Jensen - 19 Aug 2004 * Clear passwords after first use * Overwrite passwords with 0x00 before freeing memory @@ -55,6 +59,7 @@ #include "smbpw.h" #include #include +#include /* Reference counter is necissary otherwise * the sequence store, store, retrieve, retrieve @@ -67,6 +72,7 @@ char *key; char *value; int ref; /* reference counter */ + time_t mtime; /* time the value was last modified */ } *root = 0; /* clean_free_str @@ -95,7 +101,7 @@ if(strcmp((*entry)->key, key) == 0) { (*entry)->ref++; - //printf("Already an entry for key %s\n", key); + (*entry)->mtime=time(NULL); clean_free_str(&((*entry)->value)); (*entry)->value = strdup(value); @@ -108,6 +114,7 @@ new = malloc(sizeof(struct entry_t)); new->next = 0; new->ref=1; + new->mtime=time(NULL); new->key = strdup(key); new->value = strdup(value); *entry = new; @@ -115,21 +122,6 @@ return 0; } -/* scrub_memory - Write 0x00 over all passwords stored in memory before shutting down -*/ -void scrub_memory(void) -{ - struct entry_t *entry = root; - - while (entry) - { - clean_free_str(&(entry->key)); - clean_free_str(&(entry->value)); - - entry = entry->next; - } -} #ifdef DEBUG /* cache_dump @@ -141,15 +133,18 @@ { struct entry_t *entry = root; int count = 0; + char *mtime; while (entry) { count++; - printf("%i, User: %s, Password: %s, Ref: %i\n", + mtime = ctime(&(entry->mtime)); + printf("%i, User: %s, Password: %s, Ref: %i, mtime: %s\n", count, entry->key, entry->value, - entry->ref); + entry->ref, mtime); entry = entry->next; + free(mtime); } printf("Total: %i\n", count); @@ -161,24 +156,37 @@ struct entry_t *entry = root; char *password = NULL; struct entry_t **prev = &root; + time_t now = time(NULL); + int expired; while(entry) { //printf("%s, %s\n", entry->key, entry->value); if(strcmp(key, entry->key) == 0) { + expired = (difftime(now, entry->mtime) > + MAX_CACHE_AGE); + if (entry->value) { - password = strdup(entry->value); - - if ((--(entry->ref)) < 1) - { - clean_free_str(&(entry->value)); - - *prev=entry->next; - free(entry); + if (!expired) + { + password = strdup(entry->value); + (entry->ref)--; } } + + /* If the entry has expired, or has + no more processes waiting to read on it + remove it */ + if (expired || (entry->ref < 1)) + { + clean_free_str(&(entry->value)); + free(&(entry->key)); + + *prev=entry->next; + free(entry); + } return password; } prev = &entry->next; @@ -187,6 +195,29 @@ return 0; } +static void cache_flush(int flushall) +{ + struct entry_t *entry = root; + struct entry_t **prev = &root; + time_t now = time(NULL); + + while(entry) + { + if ((flushall) || (difftime(now, entry->mtime) > + MAX_CACHE_AGE)) + { + clean_free_str(&(entry->value)); + clean_free_str(&(entry->key)); + + *prev=entry->next; + free(entry); + } + + prev = &entry->next; + entry = entry->next; + } +} + static void log(int err, const char *format, ...) { va_list args; @@ -234,14 +265,14 @@ return 1; } - if(verify_socket_path(SOCKET_NAME) < 0) + if(smbpw_verify_socket_path(SOCKET_NAME) < 0) { print_version(); fprintf(stderr, "Socket path %s is insecure\n", SOCKET_NAME); return 1; } - ss = open_unix_socket(SOCKET_NAME); + ss = smbpw_open_unix_socket(SOCKET_NAME); if(ss < 0) { print_version(); @@ -307,13 +338,13 @@ { printf("STORE\n"); } - username = readstring(cs); + username = smbpw_readstring(cs); if(!username) { close(cs); continue; } - password = readstring(cs); + password = smbpw_readstring(cs); if(!password) { close(cs); @@ -331,7 +362,7 @@ { printf("RETRIEVE\n"); } - username = readstring(cs); + username = smbpw_readstring(cs); if(!username) { close(cs); @@ -360,7 +391,7 @@ printf("SHUTDOWN\n"); } log(LOG_INFO, "shutdown request. daemon terminating\n"); - scrub_memory(); + cache_flush(1); return 0; break; #ifdef DEBUG @@ -373,7 +404,22 @@ } break; #endif /* DEBUG */ - + case 0x05: + if(verbose) + { + printf("FLUSH\n"); + } + log(LOG_INFO, "Buffer flush requested. All old entries being cleaned.\n"); + cache_flush(0); + break; + case 0x06: + if(verbose) + { + printf("FLUSH ALL\n"); + } + log(LOG_INFO, "Full buffer flush requested. All entries are being removed.\n"); + cache_flush(1); + break; default: break; } --- smbpwman-0.5.orig/smbpwtest.c 2004-09-22 12:01:55.000000000 +1000 +++ smbpwman-0.5.orig/smbpwtest.c 2004-09-22 12:17:48.000000000 +1000 @@ -9,7 +9,7 @@ { char *password; - if(verify_socket_path(SOCKET_NAME) < 0) + if(smbpw_verify_socket_path(SOCKET_NAME) < 0) { fprintf(stderr, "Socket path %s is insecure\n", SOCKET_NAME); return 1; @@ -17,12 +17,12 @@ if(argc == 2 && strcmp(argv[1], "--shutdown") == 0) { - shutdown_server(); + smbpw_shutdown_server(); return 0; } else if(argc == 3 && strcmp(argv[1], "--retrieve") == 0) { - password = retrieve(argv[2]); + password = smbpw_retrieve(argv[2]); if(password) { @@ -39,13 +39,23 @@ else if(argc == 2 && strcmp(argv[1], "--dump") == 0) { printf("Requesting dump.\n"); - dump(); + smbpw_dump(); } #endif /* DEBUG */ else if(argc == 3 && strcmp(argv[1], "--store") == 0) { password = getpass("Password: "); - store(argv[2], password); + smbpw_store(argv[2], password); + } + else if(argc == 2 && strcmp(argv[1], "--flush") == 0) + { + printf("Flushing old cache entries.\n"); + smbpw_flush(0); + } + else if(argc == 2 && strcmp(argv[1], "--flushall") == 0) + { + printf("Flushing ALL cache entries.\n"); + smbpw_flush(1); } else { @@ -53,6 +63,8 @@ printf("%s --store \n", argv[0]); printf("%s --retrieve \n", argv[0]); printf("%s --shutdown\n", argv[0]); + printf("%s --flush\n", argv[0]); + printf("%s --flushall\n", argv[0]); #ifdef DEBUG printf("%s --dump\n", argv[0]); #endif /* DEBUG */