/* logon2.c
*
* version 1.4
*
* GUI Logon Screen Challenge Submission
* C version, using GTK3
*
* Written by Armando I. Rivera (AIR)
*
* Compile: gcc logon2.c $(pkg-config --libs --cflags gtk+-3.0 sqlite3) -lcrypt -o logon2
*/
#define _GNU_SOURCE
#include <gtk/gtk.h>
#include <stdio.h>
#include <crypt.h>
#include <sqlite3.h>
GtkWidget *window, *layout, *image, *btnLogin, *chkBox;
GtkWidget *lblUser, *lblPass, *txtUser, *txtPass,*err_label;
void chkBox_cb (GtkToggleButton *toggle_button, gpointer data) {
if (gtk_toggle_button_get_active (toggle_button)) {
g_object_set(data,"visibility",TRUE,NULL);
}else{
g_object_set(data,"visibility",FALSE,NULL);
}
}
void txtPass_cb( GtkWidget *widget, gpointer data ) {
g_object_set(data,"label","",NULL);
}
void txtUser_cb( GtkWidget *widget, gpointer data ) {
gtk_widget_grab_focus(data);
}
int checkPassword(gchar *user, gchar *passwd) {
sqlite3_stmt *stmt = NULL;
sqlite3 *db;
gchar *zErrMsg = 0;
int rc;
gchar *sql,*stored_password=0,*stored_salt;
gchar *hashed_password;
if (g_file_test("auth.db",G_FILE_TEST_EXISTS) == FALSE){
return(1);
}
if (rc = sqlite3_open("auth.db", &db)) {
return(2);
}
asprintf(&sql,"select username,password,salt from Users where username is '%s'",user);
if (rc = sqlite3_prepare_v2(db, sql,-1,&stmt,0) != SQLITE_OK ) {
return(-1);
}
if (sqlite3_step(stmt) == SQLITE_ROW) {
stored_password = (gchar*)sqlite3_column_text(stmt,1);
stored_salt = (gchar*)sqlite3_column_text(stmt,2);
hashed_password= crypt(passwd,stored_salt);
return g_strcmp0 (hashed_password, stored_password);
}else{
return(3);
}
}
void onClick( GtkWidget *widget, gpointer data ) {
gchar *user_name, *user_password;
int result;
g_object_get(txtUser,"text",&user_name,NULL);
g_object_get(txtPass,"text",&user_password,NULL);
result = checkPassword(user_name, user_password);
switch (result) {
case 0:
g_print("User '%s' now logged in!\n",user_name);
gtk_main_quit();
break;
case 1:
gtk_label_set_markup(GTK_LABEL(err_label), "<span color=\"red\" font_desc=\"16.0\">** Database Not Found **</span>");
g_print("'auth.db' database not found\n");
break;
case 2:
gtk_label_set_markup(GTK_LABEL(err_label), "<span color=\"red\" font_desc=\"16.0\">** Database Not Accessible**</span>");
g_print("Unable to read 'auth.db' database\n");
break;
case 3:
gtk_label_set_markup(GTK_LABEL(err_label), "<span color=\"red\" font_desc=\"16.0\">** Unknown User **</span>");
g_print("Unknown User Account for '%s'\n",user_name);
break;
default:
gtk_label_set_markup(GTK_LABEL(err_label), "<span color=\"red\" font_desc=\"16.0\">** Invalid Password **</span>");
g_print("Incorrect password for User '%s'!\n",user_name);
}
}
int main( int argc, char *argv[])
{
gtk_init(&argc, &argv);
layout = gtk_layout_new(NULL, NULL);
window = g_object_new(GTK_TYPE_WINDOW,
"type",GTK_WINDOW_TOPLEVEL,
"title","Login",
"default-width",660,
"default-height",370,
"resizable",FALSE,
"window-position",GTK_WIN_POS_CENTER,
"child",layout,
"decorated",0,
NULL);
image = g_object_new(GTK_TYPE_IMAGE,"file","logon.png",NULL);
g_object_set(layout,"child",image,"margin",10,NULL);
lblUser = g_object_new(GTK_TYPE_LABEL,"use-markup",TRUE,"label","<span font_desc=\"16.0\">Username:</span>",NULL);
lblPass = g_object_new(GTK_TYPE_LABEL,"use-markup",TRUE,"label","<span font_desc=\"16.0\">Password:</span>",NULL);
err_label = g_object_new(GTK_TYPE_LABEL, "width-request", 270,NULL);
txtUser = g_object_new(GTK_TYPE_ENTRY,NULL);
txtPass = g_object_new(GTK_TYPE_ENTRY,"visibility",FALSE,NULL);
chkBox = g_object_new(GTK_TYPE_CHECK_BUTTON,"label","Show Password",NULL);
btnLogin = g_object_new(GTK_TYPE_BUTTON,"label","Login","width-request",170,NULL);
gtk_layout_put(GTK_LAYOUT(layout), lblUser, 330, 112-30);
gtk_layout_put(GTK_LAYOUT(layout), lblPass, 330, 162-30);
gtk_layout_put(GTK_LAYOUT(layout), txtUser, 460, 110-30);
gtk_layout_put(GTK_LAYOUT(layout), txtPass, 460, 160-30);
gtk_layout_put(GTK_LAYOUT(layout), chkBox, 460, 210-30);
gtk_layout_put(GTK_LAYOUT(layout), btnLogin, 460, 250-30);
gtk_layout_put(GTK_LAYOUT(layout), err_label, 300, 16);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect (btnLogin, "clicked", G_CALLBACK (onClick), NULL);
g_signal_connect (chkBox, "toggled", G_CALLBACK (chkBox_cb), txtPass);
g_signal_connect (txtPass, "changed", G_CALLBACK (txtPass_cb), err_label);
g_signal_connect (txtPass, "activate", G_CALLBACK (onClick), txtPass);
g_signal_connect (txtUser, "activate", G_CALLBACK (txtUser_cb), txtPass);
gtk_widget_show_all(window);
gtk_main();
return 0;
}