/* * gPassgen.c-v0.07: * gPassgen is a simple GTK2 password generator that will display DES and * MD5 encrypted strings for the given password. * * Requirements: * GTK2 - http://www.gtk.org/ --- tested with 2.2.1 * * Compiling: * gcc -Wall -g gPassgen.c -o gPassgen \ * `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` -lcrypt * * Note: Solaris (others?) users don't need -lcrypt * * Tested under linux (glibc 2.3.1). * * Notes: * If target system is non-glibc, builtin support for md5 will be used. * * (c) 2003 Mike Hokenson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #define GPASSGEN_VERSION "0.07" #define GPASSGEN_URL "http://www.gozer.org/my_stuff/gtk/gPassgen.php" #define GPASSGEN_AUTHOR "2003 Mike Hokenson " #ifndef PATH_MAX # ifdef MAXPATHLEN # define PATH_MAX MAXPATHLEN # else # define PATH_MAX 1024 # endif #endif #ifndef LINE_MAX #define LINE_MAX 2048 #endif #define _PATH_RC ".gPassgenrc" /* length of generated passwords */ #define _PASS_LEN 6 /* characters used for password generation: default */ #define _PASS_CHAR "0123456789abcdefghijklmnopqrstuvwxyz" /* characters used for password generation: extended */ #define _PASS_CHAR_E "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" #define _PASS_CHAR_MAX 96 #define _PASS_CHAR_MIN 16 /* ? */ #define STREQ(s1, s2) ((strcmp(s1, s2) == 0)) #define IS_FILE(a) ((g_file_test(a, G_FILE_TEST_IS_REGULAR))) #define G_ERRMSG ((g_strerror(errno))) #define G_PERROR(a) ((g_print("%s: %s\n", a, G_ERRMSG))) enum { DES_ENC, MD5_ENC }; void gtk_window_display_preferences(GtkWidget *widget, gpointer data); void gtk_window_display_about(GtkWidget *widget, gpointer data); void gtk_update_pass_char_default(GtkWidget *widget, GtkWidget *entry); void gtk_update_pass_char_extended(GtkWidget *widget, GtkWidget *entry); void gtk_entry_pass_char_update(GtkWidget *widget, gpointer data); void gPassgen_quit(void); void gtk_entry_update(GtkWidget *widget, gpointer data); void gtk_entry_generate(GtkWidget *widget, GtkEntry *entry); void gtk_spinner_update(GtkWidget *widget, GtkWidget *spinner); /* create a button with a stock icon and custom text */ GtkWidget *gtk_button_new_custom_stock(const gchar *stock_id, const gchar *text); /* general event handler for main and about windows, close if Escape is hit */ gint gtk_window_event_handler(GtkWidget *widget, GdkEvent *event, GtkWidget *window); /* configuration related */ void load_config(void); void save_config(void); gchar *generate_password(void); gchar *crypt_string(const gchar *str, gint type); gchar *gPassgen_rc, *gPassgen_pass_char; gint gPassgen_pass_len; GtkWidget *entry_md5; GtkWidget *entry_des; gint main(gint argc, gchar **argv) { GtkWidget *window; GtkWidget *vbox; GtkWidget *vbox2; GtkWidget *hbox; GtkWidget *frame; GtkWidget *label; GtkWidget *entry; GtkWidget *button; gtk_init(&argc, &argv); gPassgen_rc = g_build_filename(g_get_home_dir(), _PATH_RC, NULL); load_config(); g_atexit(gPassgen_quit); srand((guint) time((time_t *) NULL) + getpid()); /* create a new window */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "gPassgen"); gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(window), "event", G_CALLBACK(gtk_window_event_handler), window); gtk_container_set_border_width(GTK_CONTAINER(window), 5); vbox = gtk_vbox_new(FALSE, 3); gtk_widget_show(vbox); gtk_container_add(GTK_CONTAINER(window), vbox); frame = gtk_frame_new(NULL); gtk_frame_set_label(GTK_FRAME(frame), "Password:"); gtk_frame_set_label_align(GTK_FRAME(frame), 0.0, 0.5); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); vbox2 = gtk_vbox_new(FALSE, 3); gtk_widget_show(vbox2); gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); gtk_container_add(GTK_CONTAINER(frame), vbox2); hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry), 25); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); gtk_widget_show(entry); g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(gtk_entry_update), NULL); button = gtk_button_new_custom_stock(GTK_STOCK_EXECUTE, "Generate"); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_widget_show(button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_entry_generate), entry); frame = gtk_frame_new(NULL); gtk_frame_set_label(GTK_FRAME(frame), "Encrypted:"); gtk_frame_set_label_align(GTK_FRAME(frame), 0.0, 0.5); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); vbox2 = gtk_vbox_new(FALSE, 3); gtk_widget_show(vbox2); gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); gtk_container_add(GTK_CONTAINER(frame), vbox2); hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new("DES:"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); entry_des = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry_des), 13); gtk_entry_set_editable(GTK_ENTRY(entry_des), FALSE); gtk_widget_show(entry_des); gtk_widget_set_usize(GTK_WIDGET(entry_des), 125, 0); gtk_box_pack_start(GTK_BOX(hbox), entry_des, FALSE, FALSE, 0); label = gtk_label_new(" MD5:"); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); entry_md5 = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry_md5), 34); gtk_entry_set_editable(GTK_ENTRY(entry_md5), FALSE); gtk_widget_show(entry_md5); gtk_widget_set_usize(GTK_WIDGET(entry_md5), 275, 0); gtk_box_pack_start(GTK_BOX(hbox), entry_md5, FALSE, FALSE, 0); hbox = gtk_hbox_new(TRUE, 3); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); button = gtk_button_new_custom_stock(GTK_STOCK_QUIT, "Quit"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_show(button); g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), window); button = gtk_button_new_custom_stock(GTK_STOCK_PREFERENCES, "Preferences"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_show(button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_window_display_preferences), NULL); button = gtk_button_new_custom_stock(GTK_STOCK_DIALOG_INFO, "About"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_show(button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_window_display_about), NULL); gtk_widget_show(window); { gchar *p = generate_password(); /* generate one by default? */ gtk_entry_set_text(GTK_ENTRY(entry), p); gtk_entry_select_region(GTK_ENTRY(entry), 0, -1); g_free(p); } gtk_main(); exit(0); } void gtk_window_display_preferences(GtkWidget *widget, gpointer data) { GtkWidget *window; GtkWidget *vbox; GtkWidget *vbox2; GtkWidget *vbox3; GtkWidget *hbox; GtkWidget *frame; GtkWidget *label; GtkWidget *entry; GtkWidget *button; GtkObject *adj; GtkWidget *spinner; /* create a new window */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "gPassgen: Preferences"); gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); gtk_widget_set_usize(GTK_WIDGET(window), 550, 0); g_signal_connect(G_OBJECT(window), "event", G_CALLBACK(gtk_window_event_handler), window); gtk_container_set_border_width(GTK_CONTAINER(window), 5); vbox = gtk_vbox_new(FALSE, 3); gtk_widget_show(vbox); gtk_container_add(GTK_CONTAINER(window), vbox); frame = gtk_frame_new(NULL); gtk_frame_set_label(GTK_FRAME(frame), "Password Options:"); gtk_frame_set_label_align(GTK_FRAME(frame), 0.0, 0.5); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); vbox2 = gtk_vbox_new(FALSE, 3); gtk_widget_show(vbox2); gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); gtk_container_add(GTK_CONTAINER(frame), vbox2); hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new("Length:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); gtk_widget_set_usize(GTK_WIDGET(label), 100, 0); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); adj = gtk_adjustment_new(gPassgen_pass_len, 6.0, 16.0, 1.0, 5.0, 0.0); spinner = gtk_spin_button_new((GtkAdjustment *) adj, 0, 0); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner), FALSE); gtk_box_pack_start(GTK_BOX(hbox), spinner, FALSE, FALSE, 0); gtk_widget_show(spinner); g_signal_connect(G_OBJECT(adj), "value_changed", G_CALLBACK(gtk_spinner_update), spinner); hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new("Characters:"); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); gtk_widget_set_usize(GTK_WIDGET(label), 100, 0); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); vbox3 = gtk_vbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(hbox), vbox3, TRUE, TRUE, 0); gtk_widget_show(vbox3); entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry), _PASS_CHAR_MAX); gtk_entry_set_text(GTK_ENTRY(entry), gPassgen_pass_char); gtk_box_pack_start(GTK_BOX(vbox3), entry, TRUE, TRUE, 0); gtk_widget_show(entry); g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(gtk_entry_pass_char_update), NULL); hbox = gtk_hbox_new(TRUE, 3); gtk_box_pack_start(GTK_BOX(vbox3), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); button = gtk_button_new_custom_stock(GTK_STOCK_REDO, "0-9, a-z"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_show(button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_update_pass_char_default), entry); button = gtk_button_new_custom_stock(GTK_STOCK_REFRESH, "0-9, A-Z, a-z"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_show(button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_update_pass_char_extended), entry); button = gtk_button_new_custom_stock(GTK_STOCK_OK, "OK"); gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0); gtk_widget_show(button); g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), G_OBJECT(window)); gtk_widget_show(window); } /* window: about */ void gtk_window_display_about(GtkWidget *widget, gpointer data) { GtkWidget *window; GtkWidget *vbox; GtkWidget *vbox2; GtkWidget *hbox; GtkWidget *image; GtkWidget *label; GtkWidget *button; gchar *text; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "gPassgen: About"); gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); g_signal_connect(G_OBJECT(window), "event", G_CALLBACK(gtk_window_event_handler), window); gtk_container_set_border_width(GTK_CONTAINER(window), 5); vbox = gtk_vbox_new(FALSE, 5); gtk_widget_show(vbox); gtk_container_add(GTK_CONTAINER(window), vbox); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); gtk_widget_show(image); gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.0); gtk_misc_set_padding(GTK_MISC(image), 0, 5); vbox2 = gtk_vbox_new(FALSE, 2); gtk_widget_show(vbox2); gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); gtk_container_add(GTK_CONTAINER(hbox), vbox2); label = gtk_label_new(NULL); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 5); gtk_widget_show(label); text = g_strdup_printf("gPassgen v%s", GPASSGEN_VERSION); gtk_label_set_markup(GTK_LABEL(label), text); g_free(text); label = gtk_label_new(GPASSGEN_URL); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0); gtk_widget_show(label); label = gtk_label_new(GPASSGEN_AUTHOR); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_box_pack_start(GTK_BOX(vbox2), label, FALSE, FALSE, 0); gtk_widget_show(label); button = gtk_button_new_from_stock(GTK_STOCK_OK); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); gtk_widget_show(button); g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), G_OBJECT(window)); gtk_widget_show(window); } /* window: notice dialog */ void gtk_window_display_notice(const gchar *head, const gchar *body) { GtkWidget *window; GtkWidget *vbox; GtkWidget *vbox2; GtkWidget *hbox; GtkWidget *image; GtkWidget *label; GtkWidget *button; gchar *text; g_return_if_fail(head != NULL && head[0] != '\0'); g_return_if_fail(body != NULL && body[0] != '\0'); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "gPassgen: Notice"); gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE); gtk_widget_set_usize(GTK_WIDGET(window), 425, 0); g_signal_connect(G_OBJECT(window), "event", G_CALLBACK(gtk_window_event_handler), window); gtk_container_set_border_width(GTK_CONTAINER(window), 5); vbox = gtk_vbox_new(FALSE, 5); gtk_widget_show(vbox); gtk_container_add(GTK_CONTAINER(window), vbox); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); gtk_widget_show(image); gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.0); gtk_misc_set_padding(GTK_MISC(image), 0, 5); vbox2 = gtk_vbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(hbox), vbox2, FALSE, FALSE, 0); gtk_widget_show(vbox2); gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5); label = gtk_label_new(NULL); gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, FALSE, 5); gtk_widget_show(label); gtk_widget_set_usize(GTK_WIDGET(label), 350, 0); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); text = g_strdup_printf("%s", head); gtk_label_set_markup(GTK_LABEL(label), text); g_free(text); label = gtk_label_new(body); gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, FALSE, 0); gtk_widget_show(label); gtk_widget_set_usize(GTK_WIDGET(label), 350, 0); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); gtk_widget_show(button); g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), G_OBJECT(window)); gtk_widget_show(window); } void gtk_update_pass_char_default(GtkWidget *widget, GtkWidget *entry) { gtk_entry_set_text(GTK_ENTRY(entry), _PASS_CHAR); } void gtk_update_pass_char_extended(GtkWidget *widget, GtkWidget *entry) { gtk_entry_set_text(GTK_ENTRY(entry), _PASS_CHAR_E); } void gtk_entry_pass_char_update(GtkWidget *widget, gpointer data) { g_free(gPassgen_pass_char); gPassgen_pass_char = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget))); } void gPassgen_quit(void) { save_config(); g_free(gPassgen_rc); g_free(gPassgen_pass_char); } void gtk_entry_update(GtkWidget *widget, gpointer data) { const gchar *pass = gtk_entry_get_text(GTK_ENTRY(widget)); if(pass == NULL || pass[0] == '\0') { gtk_entry_set_text(GTK_ENTRY(entry_des), ""); gtk_entry_set_text(GTK_ENTRY(entry_md5), ""); return; } gtk_entry_set_text(GTK_ENTRY(entry_des), crypt_string(pass, DES_ENC)); gtk_entry_set_text(GTK_ENTRY(entry_md5), crypt_string(pass, MD5_ENC)); } void gtk_entry_generate(GtkWidget *widget, GtkEntry *entry) { gchar *pass = generate_password(); gtk_entry_set_text(GTK_ENTRY(entry), pass); g_free(pass); } void gtk_spinner_update(GtkWidget *widget, GtkWidget *spinner) { gPassgen_pass_len = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinner)); } /* create a button with a stock icon and custom text */ GtkWidget *gtk_button_new_custom_stock(const gchar *stock_id, const gchar *text) { GtkWidget *vbox; GtkWidget *hbox; GtkWidget *button; GtkWidget *image; GtkWidget *label; /* to center the image and text in the button */ vbox = gtk_hbox_new(TRUE, 0); gtk_widget_show(vbox); hbox = gtk_hbox_new(FALSE, 2); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, FALSE, 0); image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_BUTTON); gtk_widget_show(image); gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); label = gtk_label_new(text); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); button = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button), vbox); return(button); } /* general event handler for main and about windows, close if Escape is hit */ gint gtk_window_event_handler(GtkWidget *widget, GdkEvent *event, GtkWidget *window) { switch(event->type) { case GDK_KEY_PRESS: switch(event->key.keyval) { case GDK_Escape: gtk_widget_destroy(GTK_WIDGET(window)); break; default: break; } break; default: break; } return(0); } /* supporting functions */ /* load configuration: it's not wonderful, but it works */ void load_config(void) { gchar buf[LINE_MAX]; FILE *fp; gPassgen_pass_len = _PASS_LEN; gPassgen_pass_char = g_strdup(_PASS_CHAR); if(IS_FILE(gPassgen_rc) == FALSE) return; if((fp = fopen(gPassgen_rc, "r")) == NULL) { G_PERROR("load_config: fopen: gPassgen_rc"); return; } while((fgets(buf, sizeof(buf), fp))) { gchar **p, *name, *value; buf[strlen(buf) - 1] = 0; if(buf[0] == '\0' || buf[0] == '#' || buf[0] == ' ') continue; if((p = g_strsplit(buf, "=", 2)) == NULL) continue; name = g_strdup(g_strstrip(p[0])); value = g_strdup(g_strstrip(p[1])); g_strfreev(p); if(name == NULL || value == NULL || value[0] == '\0') continue; if(STREQ(name, "pass_len")) { gint pass_len = atoi(value); if(pass_len >= 6 && pass_len <= 16) gPassgen_pass_len = pass_len; } else if(STREQ(name, "pass_char")) { gint char_len = strlen(value); g_free(gPassgen_pass_char); if(char_len >= _PASS_CHAR_MIN && char_len <= _PASS_CHAR_MAX) gPassgen_pass_char = g_strdup(value); else gPassgen_pass_char = g_strdup(""); } g_free(name); g_free(value); } fclose(fp); } /* save configuration */ void save_config(void) { FILE *fp; if((fp = fopen(gPassgen_rc, "w")) == NULL) { G_PERROR("save_config: fopen: gPassgen_rc"); return; } fprintf(fp, "# gPassgen v%s\n", GPASSGEN_VERSION); fprintf(fp, "# %s: automatically generated, do not edit.\n\n", gPassgen_rc); fprintf(fp, "pass_len = %d\n", gPassgen_pass_len); fprintf(fp, "pass_char = %s\n", g_strstrip(gPassgen_pass_char)); fclose(fp); } gchar *generate_password(void) { GString *string; gint key_len = strlen(gPassgen_pass_char); if(key_len < _PASS_CHAR_MIN) { gchar *text = g_strdup_printf("The characters used for password should not fall below %d characters, value reset to defaults.", _PASS_CHAR_MIN); gtk_window_display_notice("Source password key is too short.", text); g_free(text); gPassgen_pass_char = g_strdup(_PASS_CHAR); return(g_strdup("")); } string = g_string_new(NULL); { gint i = 0; while(i++ < gPassgen_pass_len) g_string_append_c(string, gPassgen_pass_char[rand() % key_len]); } return(g_string_free(string, FALSE)); } /* -------------------------------------------------------------------------- */ #if !(defined(__GLIBC__) && (__GLIBC__ >= 2)) /* *********************************************************************** ** md5.c -- the source code for MD5 routines ** ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** ** Created: 2/17/90 RLR ** ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** *********************************************************************** */ /* * Edited 7 May 93 by CP to change the interface to match that * of the MD5 routines in RSAREF. Due to this alteration, this * code is "derived from the RSA Data Security, Inc. MD5 Message- * Digest Algorithm". (See below.) */ /* *********************************************************************** ** Copyright(C) 1990, RSA Data Security, Inc. All rights reserved. ** ** ** ** License to copy and use this software is granted provided that ** ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** ** Digest Algorithm" in all material mentioning or referencing this ** ** software or this function. ** ** ** ** License is also granted to make and use derivative works ** ** provided that such works are identified as "derived from the RSA ** ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** ** material mentioning or referencing the derived work. ** ** ** ** RSA Data Security, Inc. makes no representations concerning ** ** either the merchantability of this software or the suitability ** ** of this software for any particular purpose. It is provided "as ** ** is" without express or implied warranty of any kind. ** ** ** ** These notices must be retained in any copies of any part of this ** ** documentation and/or software. ** *********************************************************************** */ /* typedef a 32-bit type */ #ifdef __alpha typedef unsigned int UINT4; #else typedef unsigned long int UINT4; #endif /* Data structure for MD5(Message-Digest) computation */ typedef struct { UINT4 buf[4]; /* scratch buffer */ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ unsigned char in[64]; /* input buffer */ } MD5_CTX; void MD5_Init(MD5_CTX *ctx); void MD5_Update(MD5_CTX *ctx, unsigned char *bug, unsigned int len); void MD5_Final(unsigned char digest[16], MD5_CTX *ctx); void MD5_Transform(UINT4 *buf, UINT4 *in); /* *********************************************************************** ** Message-digest routines: ** ** To form the message digest for a message M ** ** (1) Initialize a context buffer ctx using MD5_Init ** ** (2) Call MD5_Update on ctx and M ** ** (3) Call MD5_Final on ctx ** ** The message digest is now in the bugffer passed to MD5_Final ** *********************************************************************** */ unsigned char PADDING[64] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* F, G, H and I are basic MD5 functions */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ /* Rotation is separate from addition to prevent recomputation */ #define FF(a, b, c, d, x, s, ac) \ { \ (a) += F((b), (c), (d)) + (x) + (UINT4) (ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) \ { \ (a) += G((b), (c), (d)) + (x) + (UINT4) (ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) \ { \ (a) += H((b), (c), (d)) + (x) + (UINT4) (ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) \ { \ (a) += I((b), (c), (d)) + (x) + (UINT4) (ac); \ (a) = ROTATE_LEFT((a), (s)); \ (a) += (b); \ } /* The routine MD5_Init initializes the message-digest context * ctx. All fields are set to zero. */ void MD5_Init(MD5_CTX *ctx) { ctx->i[0] = ctx->i[1] = (UINT4) 0; /* Load magic initialization constants. */ ctx->buf[0] = (UINT4) 0x67452301L; ctx->buf[1] = (UINT4) 0xefcdab89L; ctx->buf[2] = (UINT4) 0x98badcfeL; ctx->buf[3] = (UINT4) 0x10325476L; } /* The routine MD5_Update updates the message-digest context to * account for the presence of each of the characters inBuf[0..inLen-1] * in the message whose digest is being computed. */ void MD5_Update(register MD5_CTX *ctx, unsigned char *inBuf, unsigned int inLen) { register int i, ii; int mdi; UINT4 in[16]; /* compute number of bytes mod 64 */ mdi = (int) ((ctx->i[0] >> 3) & 0x3F); /* update number of bits */ if((ctx->i[0] + ((UINT4) inLen << 3)) < ctx->i[0]) ctx->i[1]++; ctx->i[0] += ((UINT4) inLen << 3); ctx->i[1] += ((UINT4) inLen >> 29); while(inLen--) { /* add new character to buffer, increment mdi */ ctx->in[mdi++] = *inBuf++; /* transform if necessary */ if(mdi == 0x40) { for(i = 0, ii = 0; i < 16; i++, ii += 4) in[i] = (((UINT4) ctx->in[ii + 3]) << 24) | (((UINT4) ctx->in[ii + 2]) << 16) | (((UINT4) ctx->in[ii + 1]) << 8) | ((UINT4) ctx->in[ii]); MD5_Transform(ctx->buf, in); mdi = 0; } } } /* The routine MD5_Final terminates the message-digest computation and * ends with the desired message digest in ctx->digest[0...15]. */ void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) { UINT4 in[16]; int mdi; unsigned int i, ii; unsigned int padLen; /* save number of bits */ in[14] = ctx->i[0]; in[15] = ctx->i[1]; /* compute number of bytes mod 64 */ mdi = (int) ((ctx->i[0] >> 3) & 0x3F); /* pad out to 56 mod 64 */ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); MD5_Update(ctx, PADDING, padLen); /* append length in bits and transform */ for(i = 0, ii = 0; i < 14; i++, ii += 4) in[i] = (((UINT4) ctx->in[ii + 3]) << 24) | (((UINT4) ctx->in[ii + 2]) << 16) | (((UINT4) ctx->in[ii + 1]) << 8) | ((UINT4) ctx->in[ii]); MD5_Transform(ctx->buf, in); /* store buffer in digest */ for(i = 0, ii = 0; i < 4; i++, ii += 4) { digest[ii] = (unsigned char) (ctx->buf[i] & 0xFF); digest[ii + 1] = (unsigned char) ((ctx->buf[i] >> 8) & 0xFF); digest[ii + 2] = (unsigned char) ((ctx->buf[i] >> 16) & 0xFF); digest[ii + 3] = (unsigned char) ((ctx->buf[i] >> 24) & 0xFF); } } /* Basic MD5 step. Transforms buf based on in. Note that if the Mysterious * Constants are arranged backwards in little-endian order and decrypted with * the DES they produce OCCULT MESSAGES! */ void MD5_Transform(register UINT4 *buf, register UINT4 *in) { register UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; /* Round 1 */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 FF(a, b, c, d, in[0], S11, 0xD76AA478L); /* 1 */ FF(d, a, b, c, in[1], S12, 0xE8C7B756L); /* 2 */ FF(c, d, a, b, in[2], S13, 0x242070DBL); /* 3 */ FF(b, c, d, a, in[3], S14, 0xC1BDCEEEL); /* 4 */ FF(a, b, c, d, in[4], S11, 0xF57C0FAFL); /* 5 */ FF(d, a, b, c, in[5], S12, 0x4787C62AL); /* 6 */ FF(c, d, a, b, in[6], S13, 0xA8304613L); /* 7 */ FF(b, c, d, a, in[7], S14, 0xFD469501L); /* 8 */ FF(a, b, c, d, in[8], S11, 0x698098D8L); /* 9 */ FF(d, a, b, c, in[9], S12, 0x8B44F7AFL); /* 10 */ FF(c, d, a, b, in[10], S13, 0xFFFF5BB1L); /* 11 */ FF(b, c, d, a, in[11], S14, 0x895CD7BEL); /* 12 */ FF(a, b, c, d, in[12], S11, 0x6B901122L); /* 13 */ FF(d, a, b, c, in[13], S12, 0xFD987193L); /* 14 */ FF(c, d, a, b, in[14], S13, 0xA679438EL); /* 15 */ FF(b, c, d, a, in[15], S14, 0x49B40821L); /* 16 */ /* Round 2 */ #define S21 5 #define S22 9 #define S23 14 #define S24 20 GG(a, b, c, d, in[1], S21, 0xF61E2562L); /* 17 */ GG(d, a, b, c, in[6], S22, 0xC040B340L); /* 18 */ GG(c, d, a, b, in[11], S23, 0x265E5A51L); /* 19 */ GG(b, c, d, a, in[0], S24, 0xE9B6C7AAL); /* 20 */ GG(a, b, c, d, in[5], S21, 0xD62F105DL); /* 21 */ GG(d, a, b, c, in[10], S22, 0x02441453L); /* 22 */ GG(c, d, a, b, in[15], S23, 0xD8A1E681L); /* 23 */ GG(b, c, d, a, in[4], S24, 0xE7D3FBC8L); /* 24 */ GG(a, b, c, d, in[9], S21, 0x21E1CDE6L); /* 25 */ GG(d, a, b, c, in[14], S22, 0xC33707D6L); /* 26 */ GG(c, d, a, b, in[3], S23, 0xF4D50D87L); /* 27 */ GG(b, c, d, a, in[8], S24, 0x455A14EDL); /* 28 */ GG(a, b, c, d, in[13], S21, 0xA9E3E905L); /* 29 */ GG(d, a, b, c, in[2], S22, 0xFCEFA3F8L); /* 30 */ GG(c, d, a, b, in[7], S23, 0x676F02D9L); /* 31 */ GG(b, c, d, a, in[12], S24, 0x8D2A4C8AL); /* 32 */ /* Round 3 */ #define S31 4 #define S32 11 #define S33 16 #define S34 23 HH(a, b, c, d, in[5], S31, 0xFFFA3942L); /* 33 */ HH(d, a, b, c, in[8], S32, 0x8771F681L); /* 34 */ HH(c, d, a, b, in[11], S33, 0x6D9D6122L); /* 35 */ HH(b, c, d, a, in[14], S34, 0xFDE5380CL); /* 36 */ HH(a, b, c, d, in[1], S31, 0xA4BEEA44L); /* 37 */ HH(d, a, b, c, in[4], S32, 0x4BDECFA9L); /* 38 */ HH(c, d, a, b, in[7], S33, 0xF6BB4B60L); /* 39 */ HH(b, c, d, a, in[10], S34, 0xBEBFBC70L); /* 40 */ HH(a, b, c, d, in[13], S31, 0x289B7EC6L); /* 41 */ HH(d, a, b, c, in[0], S32, 0xEAA127FAL); /* 42 */ HH(c, d, a, b, in[3], S33, 0xD4EF3085L); /* 43 */ HH(b, c, d, a, in[6], S34, 0x04881D05L); /* 44 */ HH(a, b, c, d, in[9], S31, 0xD9D4D039L); /* 45 */ HH(d, a, b, c, in[12], S32, 0xE6DB99E5L); /* 46 */ HH(c, d, a, b, in[15], S33, 0x1FA27CF8L); /* 47 */ HH(b, c, d, a, in[2], S34, 0xC4AC5665L); /* 48 */ /* Round 4 */ #define S41 6 #define S42 10 #define S43 15 #define S44 21 II(a, b, c, d, in[0], S41, 0xF4292244L); /* 49 */ II(d, a, b, c, in[7], S42, 0x432AFF97L); /* 50 */ II(c, d, a, b, in[14], S43, 0xAB9423A7L); /* 51 */ II(b, c, d, a, in[5], S44, 0xFC93A039L); /* 52 */ II(a, b, c, d, in[12], S41, 0x655B59C3L); /* 53 */ II(d, a, b, c, in[3], S42, 0x8F0CCC92L); /* 54 */ II(c, d, a, b, in[10], S43, 0xFFEFF47DL); /* 55 */ II(b, c, d, a, in[1], S44, 0x85845DD1L); /* 56 */ II(a, b, c, d, in[8], S41, 0x6FA87E4FL); /* 57 */ II(d, a, b, c, in[15], S42, 0xFE2CE6E0L); /* 58 */ II(c, d, a, b, in[6], S43, 0xA3014314L); /* 59 */ II(b, c, d, a, in[13], S44, 0x4E0811A1L); /* 60 */ II(a, b, c, d, in[4], S41, 0xF7537E82L); /* 61 */ II(d, a, b, c, in[11], S42, 0xBD3AF235L); /* 62 */ II(c, d, a, b, in[2], S43, 0x2AD7D2BBL); /* 63 */ II(b, c, d, a, in[9], S44, 0xEB86D391L); /* 64 */ buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } /* -------------------------------------------------------------------------- */ /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- */ /* * Ported from FreeBSD to Linux, only minimal changes. --marekm */ unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; char *magic = "$1$"; /* * This string is magic for * this algorithm. Having * it this way, we can get * get better later on */ int magic_len = 3; void to64(char *s, unsigned long v, int n) { while (--n >= 0) { *s++ = itoa64[v&0x3f]; v >>= 6; } } char *md5_crypt(unsigned char *pw, const char *salt) { static char passwd[120], *p; static const char *sp, *ep; unsigned char final[16]; int sl,pl,i,j,pw_len = strlen(pw); MD5_CTX ctx,ctx1; unsigned long l; /* Refine the Salt first */ sp = salt; /* If it starts with the magic string, then skip that */ if(!strncmp(sp, magic, magic_len)) sp += magic_len; /* It stops at the first '$', max 8 chars */ for(ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++) continue; /* get the length of the true salt */ sl = ep - sp; MD5_Init(&ctx); /* The password first, since that is what is most unknown */ MD5_Update(&ctx, pw, pw_len); /* Then our magic string */ MD5_Update(&ctx, magic, magic_len); /* Then the raw salt */ MD5_Update(&ctx, (unsigned char *) sp, sl); /* Then just as many characters of the MD5(pw, salt, pw) */ MD5_Init(&ctx1); MD5_Update(&ctx1, pw, pw_len); MD5_Update(&ctx1, (unsigned char *) sp, sl); MD5_Update(&ctx1, pw, pw_len); MD5_Final(final, &ctx1); for(pl = pw_len; pl > 0; pl -= 16) MD5_Update(&ctx, final, pl > 16 ? 16 : pl); /* Don't leave anything around in vm they could use. */ memset(final, 0, sizeof(final)); /* Then something really weird... */ for (j = 0, i = pw_len; i ; i >>= 1) if(i & 1) MD5_Update(&ctx, final + j, 1); else MD5_Update(&ctx, pw + j, 1); /* Now make the output string */ strcpy(passwd, magic); strncat(passwd, sp, sl); strcat(passwd, "$"); MD5_Final(final, &ctx); /* * and now, just to make sure things don't run too fast * On a 60 Mhz Pentium this takes 34 msec, so you would * need 30 seconds to build a 1000 entry dictionary... */ for(i = 0; i < 1000; i++) { MD5_Init(&ctx1); if(i & 1) MD5_Update(&ctx1, pw, pw_len); else MD5_Update(&ctx1, final, 16); if(i % 3) MD5_Update(&ctx1, (unsigned char *) sp, sl); if(i % 7) MD5_Update(&ctx1, pw, pw_len); if(i & 1) MD5_Update(&ctx1, final, 16); else MD5_Update(&ctx1, pw, pw_len); MD5_Final(final, &ctx1); } p = passwd + strlen(passwd); l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; l = final[11] ; to64(p,l,2); p += 2; *p = '\0'; /* Don't leave anything around in vm they could use. */ memset(final, 0, sizeof(final)); return(passwd); } #endif /* !(defined(__GLIBC__) && (__GLIBC__ >= 2)) */ /* -------------------------------------------------------------------------- */ /* * Copyright 1989 - 1992, Julianne Frances Haugh * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Julianne F. Haugh nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * i64c - convert an integer to a radix 64 character */ int i64c(int i) { if(i <= 0) return('.'); if(i == 1) return('/'); if(i >= 2 && i < 12) return('0' - 2 + i); if(i >= 12 && i < 38) return('A' - 12 + i); if(i >= 38 && i < 63) return('a' - 38 + i); return('z'); } /* * l64a - convert a long to a string of radix 64 characters */ char *l64a(long l) { static char buf[8]; int i = 0; if(l < 0L) return ((char *) 0); do { buf[i++] = i64c ((int) (l % 64)); buf[i] = '\0'; } while(l /= 64L, l > 0 && i < 6); return(buf); } /* -------------------------------------------------------------------------- */ /* * salt.c - generate a random salt string for crypt() * * Written by Marek Michalkiewicz , * public domain. */ /* * Generate 8 base64 ASCII characters of random salt. If MD5_CRYPT_ENAB * in /etc/login.defs is "yes", the salt string will be prefixed by "$1$" * (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible * version of crypt() instead of the standard one. */ const char *crypt_make_salt(int type) { struct timeval tv; static char result[40]; result[0] = '\0'; if(type == MD5_ENC) strcpy(result, "$1$"); /* magic for the new MD5 crypt() */ /* * Generate 8 chars of salt, the old crypt() will use only first 2. */ gettimeofday(&tv, (struct timezone *) 0); strcat(result, l64a(tv.tv_usec)); strcat(result, l64a(tv.tv_sec + getpid() + clock())); if(strlen(result) > 3 + 8) /* magic+salt */ result[11] = '\0'; return(result); } /* -------------------------------------------------------------------------- */ gchar *crypt_string(const gchar *str, gint type) { const gchar *salt = crypt_make_salt(type); switch(type) { case MD5_ENC: #if !(defined(__GLIBC__) && (__GLIBC__ >= 2)) return(md5_crypt((guchar *) str, salt)); #else return(crypt(str, salt)); #endif case DES_ENC: return(crypt(str, salt)); default: break; } return("unknown type"); } /* * --- Changelog -------------------------------------------------------------- * * 0.01 - 2/25/2003: * initial release. * * 0.02 - 2/25/2003: * fixed an overflow error in my_md5_crypt_(glibc|builtin)() on salt[] * that didn't show up with gcc 3.2. :I * added quit, preferences and about buttons, windows. * added config loading/saving. * password length can be set, minimum length is 6, maximum is 16. * source password characters can be configured and include two pre-defined * values: 0-9, a-z (default) and 0-9, A-Z, a-z. additional chars can be * added. * added a minimum and maximum password source key length, if it falls * below the minimum value (16) and a generate password is attempted, * a small notice window will be displayed and default value reset. * * 0.03 - 2/26/2003: * minor cleanups. * * 0.04 - 2/26/2003: * minor cleanups. * * 0.05 - 3/15/2003: * a few memory related cleanups. * other minor cleanups. * * 0.06 - 10/1/2003: * sync with crypt_string. * other minor cleanups. * * 0.07 - 11/12/2003: * minor cleanups. * * --- Changelog -------------------------------------------------------------- */