/* * PWDB2CSV - Convert pwman database files into Comma Separated Values * * Copyright (C) 2002 Ivan Kelly * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define STR_LEN 255 #define PWDB2CSV_PACKAGE "PWDB2CSV" #define PWDB2CSV_VERSION "0.1.0" #include #include #include #include static void show_version(); static void show_usage(char*); struct PWDB2CSV_Options { char *gpg_id; char *infile; char *outfile; } pwdb2csv_options; void debug(char *fmt, ... ) { #ifdef DEBUG va_list ap; int d, c; char *s; fputs("PWDB2CSV Debug% ", stderr); va_start(ap, fmt); while(*fmt){ if(*fmt == '%'){ switch(*++fmt){ case 's': /* string */ s = va_arg(ap, char*); fputs(s, stderr); break; case 'd': /* int */ d = va_arg(ap, int); fprintf(stderr, "%d", d); break; case 'c': /* char */ c = va_arg(ap, int); fputc(c, stderr); break; default: fputc('%', stderr); fputc(*fmt, stderr); break; } } else { fputc(*fmt, stderr); } *fmt++; } va_end(ap); fputc('\n', stderr); #endif } PWList * new_pwlist(char *name) { PWList *new; new = malloc( sizeof(PWList) ); new->name = malloc(STRING_MEDIUM); strncpy(new->name, name, STRING_MEDIUM); new->parent = NULL; new->list = NULL; new->sublists = NULL; debug("new_pwlist: %s", name); return new; } int free_pwlist(PWList *old) { Pw *current, *next; PWList *curlist, *nlist; debug("free_pwlist: free a password list"); if(old == NULL){ return 0; } for(current = old->list; current != NULL; current = next){ next = current->next; free_pw(current); } for(curlist = old->sublists; curlist != NULL; curlist = nlist){ nlist = curlist->next; free_pwlist(curlist); } free(old->name); free(old); old = NULL; return 0; } Pw* new_pw() { Pw *new; new = malloc(sizeof(Pw)); new->id = 0; new->name = malloc(STRING_MEDIUM); new->host = malloc(STRING_MEDIUM); new->user = malloc(STRING_MEDIUM); new->passwd = malloc(STRING_SHORT); new->launch = malloc(STRING_LONG); memset(new->name, 0, STRING_MEDIUM); memset(new->host, 0, STRING_MEDIUM); memset(new->user, 0, STRING_MEDIUM); memset(new->passwd, 0, STRING_SHORT); memset(new->launch, 0, STRING_LONG); return new; } int free_pw(Pw *old) { debug("free_pw: free a password"); free(old->name); free(old->user); free(old->host); free(old->passwd); free(old->launch); free(old); } int add_pw_ptr(PWList *list, Pw *new) { Pw *current; if(list == NULL){ debug("add_pw_ptr : Bad PwList"); return -1; } if(new == NULL){ debug("add_pw_ptr : Bad Pw"); return -1; } if(list->list == NULL){ list->list = new; new->next = NULL; return 0; } debug("add_pw_ptr: add to list"); current = list->list; while(current->next != NULL){ current = current->next; } current->next = new; new->next = NULL; return 0; } int add_pw_sublist(PWList *parent, PWList *new) { PWList *current; current = parent->sublists; new->parent = parent; if(current == NULL){ parent->sublists = new; new->next = NULL; return 0; } while(current->next != NULL){ current = current->next; } current->next = new; new->next = NULL; return 0; } char * escape_string(char *str) { char *str2, *iter, *iter2, *c; int i = 0; str2 = malloc( strlen(str) + 100 ); /* any string with 100 quotes is a pisstake , it's just here for safety */ for(iter = str, iter2 = str2; iter != 0, i < 100; iter++, iter2++, i++){ if(*iter != '"'){ *iter2 = *iter; } else { *iter2 = '\\'; iter2++; *iter2 = *iter; } } free(str); str = str2; return str; } int write_password_node(FILE *fp, Pw *pw) { fprintf(fp, "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n", escape_string(pw->name), escape_string(pw->host), escape_string(pw->user), escape_string(pw->passwd), escape_string(pw->launch)); } int write_pwlist(FILE *fp, PWList *pwlist) { Pw* iter; PWList *pwliter; for(pwliter = pwlist->sublists; pwliter != NULL; pwliter = pwliter->next){ write_pwlist(fp, pwliter); } for(iter = pwlist->list; iter != NULL; iter = iter->next){ write_password_node(fp, iter); } return 0; } void read_password_node(xmlNodePtr parent, PWList *list) { Pw *new; xmlNodePtr node; char *text; new = new_pw(); for(node = parent->children; node != NULL; node = node->next){ if(!node || !node->name){ debug("read_pw_node: fucked node"); } else if( strcmp((char*)node->name, "name") == 0){ text = (char*)xmlNodeGetContent(node); if(text) strncpy(new->name, text, STRING_MEDIUM); } else if( strcmp((char*)node->name, "user") == 0){ text = (char*)xmlNodeGetContent(node); if(text) strncpy(new->user, text, STRING_MEDIUM); } else if( strcmp((char*)node->name, "passwd") == 0){ text = (char*)xmlNodeGetContent(node); if(text) strncpy(new->passwd, text, STRING_SHORT); } else if( strcmp((char*)node->name, "host") == 0){ text = (char*)xmlNodeGetContent(node); if(text) strncpy(new->host, text, STRING_MEDIUM); } else if( strcmp((char*)node->name, "launch") == 0){ text = (char*)xmlNodeGetContent(node); if(text) strncpy(new->launch, text, STRING_LONG); } else { debug("read_pw_node: unrecognised node \"%s\"", node->name); } } add_pw_ptr(list, new); } int read_pwlist(xmlNodePtr parent, PWList *parent_list) { xmlNodePtr node; PWList *new; char name[STRING_MEDIUM]; if(!parent || !parent->name){ return -1; } debug("Parent name is %s\n", parent->name); if(strcmp((char*)parent->name, "PwList") == 0){ strncpy(name, xmlGetProp(parent, (xmlChar*)"name"), STRING_MEDIUM); new = new_pwlist(name); for(node = parent->children; node != NULL; node = node->next){ debug("Child name is %s\n", node->name); if(!node) { fprintf(stderr, "read_pwlist: messed up node - null\n"); // Doesn't appear to be a problem // } else if(!node->next){ // fprintf(stderr, "read_pwlist: messed up node - no next sibling\n"); } else if(strcmp(node->name, "PwList") == 0){ read_pwlist(node, new); } else if(strcmp(node->name, "PwItem") == 0){ read_password_node(node, new); } } } if(parent_list == NULL){ parent_list = new; } else { add_pw_sublist(parent_list, new); } return 0; } PWList* parse_doc(xmlDocPtr doc) { PWList *pwlist = NULL; xmlNodePtr root, node; char *buf; int i; if(!doc){ return NULL; } root = xmlDocGetRootElement(doc); if(!root || !root->name || (strcmp((char*)root->name, "PWMan_PasswordList") != 0) ){ return NULL; } if(buf = xmlGetProp(root, (xmlChar*)"version")){ i = atoi( buf ); } else { i = 0; } if(i < FF_VERSION){ return NULL; } pwlist = new_pwlist("Main"); for(node = root->children; node != NULL; node = node->next){ if(strcmp(node->name, "PwList") == 0){ read_pwlist(node, pwlist); break; } } xmlFreeDoc(doc); return pwlist; } char * add_to_buf(char *buf, char *new) { size_t size; if(new == NULL){ return buf; } if(buf == NULL){ buf = malloc(strlen(new)+1); strncpy(buf, new, strlen(new)+1); return buf; } size = strlen(buf) + strlen(new) + 1; buf = (char*)realloc(buf, size); strncat(buf, new, size); return buf; } xmlDocPtr get_data() { FILE *fp; char *cmd; char *data; char buf[STR_LEN]; xmlDocPtr doc; data = NULL; cmd = malloc(STR_LEN); snprintf(cmd, STR_LEN, "gpg -d %s", pwdb2csv_options.infile); debug(cmd); fp = popen(cmd, "r"); while( fgets(buf, STR_LEN, fp) != NULL ){ data = add_to_buf(data, buf); } pclose(fp); if(!data){ exit(-1); } doc = xmlParseMemory(data, strlen(data)); return doc; } void put_data(PWList *pwlist) { FILE *fp; fp = fopen(pwdb2csv_options.outfile, "w"); if(!fp){ fprintf(stderr, "write_pwlist: couldn't open file \"%s\"\n", pwdb2csv_options.outfile); return; } write_pwlist(fp, pwlist); fclose(fp); } void free_pwdb2csv_options() { debug("free_pwdb2csv_options: free options"); free(pwdb2csv_options.infile); free(pwdb2csv_options.outfile); } char * ask(char *msg) { char * input; input = malloc(STR_LEN); fputs(msg, stdout); fputc('\t', stdout); fgets(input, STR_LEN, stdin); input[ strlen(input) - 1] = 0; return input; } void get_options(int argc, char *argv[]) { int i; for(i = 0; i < argc; i++){ if( !strcmp(argv[i], "--help") || !strcmp(argv[i], "-h") ){ show_usage(argv[0]); exit(1); } else if( !strcmp(argv[i], "--version") || !strcmp(argv[i], "-v") ){ show_version(); exit(1); } } if(argc > 1){ pwdb2csv_options.infile = malloc(STR_LEN); strncpy(pwdb2csv_options.infile, argv[1], STR_LEN); } else { pwdb2csv_options.infile = ask("Password Database:"); } if(argc > 2){ pwdb2csv_options.outfile = malloc(STR_LEN); strncpy(pwdb2csv_options.outfile, argv[2], STR_LEN); } else { pwdb2csv_options.outfile = ask("CSV file:"); } } int main(int argc, char *argv[]) { xmlDocPtr doc; PWList *pwlist; get_options(argc, argv); doc = get_data(); pwlist = parse_doc(doc); put_data(pwlist); free_pwdb2csv_options(); return 0; } static void show_version() { puts(PWDB2CSV_PACKAGE " v " PWDB2CSV_VERSION); puts("Written by Ivan Kelly \n"); puts("Copyright (C) 2002 Ivan Kelly"); puts("This program is free software; you can redistribute it and/or modify"); puts("it under the terms of the GNU General Public License as published by"); puts("the Free Software Foundation; either version 2 of the License, or"); puts("(at your option) any later version.\n"); puts("This program is distributed in the hope that it will be useful,"); puts("but WITHOUT ANY WARRANTY; without even the implied warranty of"); puts("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"); puts("GNU General Public License for more details.\n"); puts("You should have received a copy of the GNU General Public License"); puts("along with this program; if not, write to the Free Software"); puts("Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.\n"); } static void show_usage(char *argv_0) { printf("Usage: %s [ []]\n", argv_0); puts("Convert Password Database from PWMan Encrypted Format to Comma Separated Values\n"); puts(" --help show usage"); puts(" --version display version information"); puts(" password database file in encrypted"); puts(" file to write to with comma separated values\n\n"); puts("Report bugs to "); }