/* client_session.c -- Handles eurephia session in admin clients * * GPLv2 only - Copyright (C) 2008, 2009 * David Sommerseth * * 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; version 2 * of the License. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "client_config.h" char *get_session_file() { char *fname = NULL; fname = get_config_filename("EUREPHIADM_SESSION","/session"); if( fname == NULL ) { // If even default ~/.eurephia dir failed, create one in /tmp snprintf(fname, 1024, "/tmp/.eurepia-%i.sess", getuid()); return fname; } return fname; } char *read_session_file(eurephiaCTX *ctx) { char *sesskey = NULL, *fname = NULL; FILE *sfp = NULL; fname = get_session_file(); assert(fname != NULL); if( (sfp = fopen(fname, "r")) == NULL ) { return NULL; } sesskey = (char *) malloc(256); assert( sesskey != NULL ); memset(sesskey, 0, 256); if( (fgets(sesskey, 254, sfp) == NULL) || (strlen_nullsafe(sesskey) < 64) ) { eurephia_log(ctx, LOG_PANIC, 0, "Could not read session file (%s). Session value too short", fname); return NULL; } fclose(sfp); return sesskey; } int write_session_file(eurephiaCTX *ctx, eurephiaSESSION *sess) { struct stat fchk; char *fname = NULL; FILE *sfp = NULL; assert((ctx != NULL) && (sess != NULL) && (sess->sessionkey != NULL)); fname = get_session_file(); assert(fname != NULL); if( stat(fname, &fchk) != -1 ) { // session file exists, do not update it return 1; } if( (sfp = fopen(fname, "w")) == NULL ) { eurephia_log(ctx, LOG_PANIC, 0, "Could not create session file (%s). Operation aborted.", fname); return 0; } fprintf(sfp, "%s", sess->sessionkey); fclose(sfp); return 1; } void remove_session_file(eurephiaCTX *ctx) { const char *fname = NULL; fname = get_session_file(); assert(fname != NULL); if( unlink(fname) == -1) { eurephia_log(ctx, LOG_ERROR, 0, "Could not remove session file (%s). Following operations might fail", fname); }; } eurephiaSESSION *create_session(eurephiaCTX *ctx, const char *sesskey) { eurephiaSESSION *new_sess = NULL; int loop, uniqchk; char *randdata = NULL; unsigned char sha_res[SHA512_HASH_SIZE+2]; SHA512Context sha; new_sess = (eurephiaSESSION *) malloc(sizeof(eurephiaSESSION) + 2); assert(new_sess != NULL); memset(new_sess, 0, sizeof(eurephiaSESSION) + 2); if( sesskey == NULL ) { // Get data for a unique session key randdata = (char *) malloc(514); assert(randdata != NULL); do { char *ptr = NULL; int i = 0; memset(randdata, 0, 514); if( !eurephia_randstring(ctx, randdata, 512) ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not generate enough random data for session"); free_nullsafe(randdata); free_nullsafe(new_sess); return NULL; } memset(&sha, 0, sizeof(SHA512Context)); memset(&sha_res, 0, SHA512_HASH_SIZE+2); free_nullsafe(new_sess->sessionkey); new_sess->sessionkey = (char *) malloc((SHA512_HASH_SIZE*2) + 3); assert(new_sess->sessionkey != NULL); memset(new_sess->sessionkey, 0, (SHA512_HASH_SIZE*2) + 3); SHA512Init(&sha); SHA512Update(&sha, randdata, 512); SHA512Final(&sha, sha_res); ptr = new_sess->sessionkey; for( i = 0; i < SHA512_HASH_SIZE; i++ ) { sprintf(ptr, "%02x", sha_res[i]); ptr++; } memset(&sha, 0, sizeof(SHA512Context)); memset(&sha_res, 0, sizeof(sha_res)); loop++; uniqchk = eDBcheck_sessionkey_uniqueness(ctx, new_sess->sessionkey); } while( (uniqchk == 0) && (loop < 11) ); free_nullsafe(randdata); if( uniqchk == 0 ) { eurephia_log(ctx, LOG_FATAL, 0, "Did not manage to create a unique session key after %i attemtps. Aborting.", loop-1); free_nullsafe(new_sess->sessionkey); free_nullsafe(new_sess); return NULL; } } else { new_sess->sessionkey = strdup(sesskey); new_sess->sessvals = eDBload_sessiondata(ctx, new_sess->sessionkey); } // Return new session return new_sess; }