/Users/maurits/Documents/studie/afstuderen/biosphere/modules/password/bsmod_password.c

Go to the documentation of this file.
00001 /*
00002  * Author: MA Hartman
00003  * Date: may 10, 2007
00004  * 
00005  * Function:
00006  * A module which offers password services.
00007  * 
00008  * License information:
00009  * 
00010  * Copyright (c) 2006 Maurits Hartman
00011  *
00012  * Permission is hereby granted, free of charge, to any person
00013  * obtaining a copy of this software and associated documentation
00014  * files (the "Software"), to deal in the Software without
00015  * restriction, including without limitation the rights to use,
00016  * copy, modify, merge, publish, distribute, sublicense, and/or sell
00017  * copies of the Software, and to permit persons to whom the
00018  * Software is furnished to do so, subject to the following
00019  * conditions:
00020  * 
00021  * The above copyright notice and this permission notice shall be
00022  * included in all copies or substantial portions of the Software.
00023  * 
00024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00026  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00028  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00029  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00030  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00031  * OTHER DEALINGS IN THE SOFTWARE.
00032  * 
00033  */
00034 
00035 #include <biosphere_module.h>
00036 #include <io.h>
00037 #include <list.h>
00038 #include <str.h>
00039 #include <type.h>
00040 
00041 #include <apr_strings.h>
00042 #include <stdio.h>
00043 #include <openssl/sha.h>
00044 
00045 
00052 #define BSMOD_PASSWORD_FILE "passwd"
00053 
00054 apr_pool_t *password_pool;
00055 bs_list *password_list;
00056 
00057 
00058 bs_module bsmod_symtable;
00059 
00060 
00065 typedef struct password_entry {
00066         const char *username;   
00067         const char *hash;               
00068 } password_entry;
00069 
00070 
00077 static char *hash_string(const char *str)
00078 {
00079         unsigned char md[SHA_DIGEST_LENGTH];
00080         char *ret = "";
00081         unsigned i;
00082         
00083         SHA1((unsigned char *) str, strlen(str), md);
00084         for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
00085                 char *d = apr_psprintf(password_pool, "%02x", md[i] & 0xff);
00086                 ret = apr_pstrcat(password_pool, ret, d, NULL);
00087         }
00088         return ret;
00089 }
00090 
00091 
00099 static bs_status add_user(const char *name, const char *pass)
00100 {
00101         char *hash;
00102         unsigned i;
00103         password_entry *entry;
00104         
00105         /* Check whether the user is not yet present: */
00106         for (i = 0; i < list_size(password_list); i++) {
00107                 password_entry *e = (password_entry *) list_index(password_list, i);
00108                 if (streq(e->username, name)) return BS_ERROR;
00109         }
00110         
00111         hash = hash_string(pass);
00112         entry = (password_entry *) apr_palloc(password_pool,
00113                         sizeof(password_entry));
00114         entry->username = apr_pstrdup(password_pool, name);
00115         entry->hash = hash;
00116         list_append(password_list, entry);
00117         return BS_OK;
00118 }
00119 
00120 
00126 static bs_status remove_user(const char *name)
00127 {
00128         unsigned i;
00129         for (i = 0; i < list_size(password_list); i++) {
00130                 password_entry *e = (password_entry *) list_index(password_list, i);
00131                 if (streq(e->username, name)) {
00132                         list_remove(password_list, i);
00133                         return BS_OK;
00134                 }
00135         }
00136         return BS_OK;
00137 }
00138 
00139 
00144 static bs_status bsmod_password_init(void)
00145 {
00146         char *pfilename, *pfilecontents;
00147         bs_uint64 len;
00148         bs_status rv;
00149         bs_list *list;
00150         
00151         /* Create pool, mutexes and open password file: */
00152         apr_pool_create(&password_pool, NULL);
00153         pfilename = apr_pstrcat(password_pool,
00154                         "/usr/local/biosphere/modules/", BSMOD_PASSWORD_FILE, NULL);
00155         rv = read_file_into_buf(pfilename, &pfilecontents, &len, password_pool);
00156         if (rv != BS_OK || len == 0) {
00157                 apr_pool_destroy(password_pool);
00158                 return BS_ERROR;
00159         }
00160         
00161         /* Process the password file's contents: */
00162         list = new_list(password_pool);
00163         strtokenize(list, pfilecontents, NULL);
00164         if (list_size(list) % 2 == 1) {
00165                 apr_pool_destroy(password_pool);
00166                 return BS_ERROR;        
00167         }
00168         else {
00169                 unsigned i;
00170                 
00171                 /* Make entries and add to password list: */
00172                 password_list = new_list(password_pool);
00173                 for (i = 0 ; i < list_size(list); i += 2) {
00174                         password_entry *entry;
00175                         
00176                         entry = (password_entry *) apr_palloc(password_pool,
00177                                         sizeof(password_entry));
00178                         entry->username = apr_pstrdup(password_pool,
00179                                         (char *) list_index(list, i));
00180                         entry->hash = apr_pstrdup(password_pool,
00181                                         (char *) list_index(list, i + 1));
00182                         list_append(password_list, entry);
00183                 }
00184         }
00185         
00186         return BS_OK;
00187 }
00188 
00189 
00193 static bs_status bsmod_password_cleanup(void)
00194 {
00195         char *passes = "", *pfilename;
00196         unsigned i;
00197         bs_status rv;
00198         
00199         /* Write the passwords to the password file: */
00200         for (i = 0; i < list_size(password_list); i++) {
00201                 password_entry *e = (password_entry *) list_index(password_list, i);
00202                 passes = apr_pstrcat(password_pool, passes,
00203                                 e->username, " ", e->hash, "\n", NULL);
00204         }
00205         pfilename = apr_pstrcat(password_pool,
00206                         "/usr/local/biosphere/modules/", BSMOD_PASSWORD_FILE, NULL);
00207         rv = write_buf_into_file(pfilename, passes, password_pool);
00208         if (rv != BS_OK) return rv;
00209         
00210         apr_pool_destroy(password_pool);
00211         return BS_OK;   
00212 }
00213 
00214 
00215 static bs_service_response *create_status_response(
00216                 const bs_service_request *request, bs_status status)
00217 {
00218         bs_service_response *resp;
00219         bs_message_instance *output = NULL;
00220         bs_part_instance *part = NULL;
00221         bs_data_type *type = NULL;
00222         char *data;
00223         apr_pool_t *mp = password_pool;
00224         
00225         data = apr_psprintf(mp, "%u", status);
00226         type = new_bs_data_type(mp, "bs_uint32");
00227         if (!type) return NULL;
00228         part = new_bs_part_instance(mp, "status", type,
00229                         data, strlen(data));
00230         if (!part) return NULL;
00231         output = new_bs_message_instance(mp, "BSStatusMessage", 1);
00232         if (!output) return NULL;
00233         output->parts[0] = part;
00234         resp = new_bs_service_response(mp, request->uuid,
00235                         request->service, request->port, request->operation,
00236                         output, NULL);
00237         
00238         return resp;
00239 }
00240 
00241 
00245 static bs_status bsmod_password_handle_service(
00246                 const bs_service_request *request,
00247                 bs_service_response **response, void *extra)
00248 {
00249         bs_status rv;
00250         
00251         /* Precondition checks: */
00252         if (!streq(request->service, "BSModPasswordServices"))
00253                 return BS_NO_SERVICE;
00254         if (!streq(request->port, "Password"))
00255                 return BS_NO_SERVICE;
00256         
00257         /* Handle the operation: */
00258         if (streq(request->operation, "verify_user")) {
00259                 char *name, *pass;
00260                 unsigned i;
00261                 
00262                 rv = 0;
00263                 if (request->input->num_parts != 2) return BS_ERROR;
00264                 name = request->input->parts[0]->data;
00265                 pass = request->input->parts[1]->data;
00266                 for (i = 0; i < list_size(password_list); i++) {
00267                         password_entry *e = (password_entry *) list_index(password_list, i);
00268                         if (streq(e->username, name) && streq(e->hash, hash_string(pass))) {
00269                                 /* TODO: should improve: genuine is 1, imposter = 0 */
00270                                 rv = 1;
00271                         }
00272                 }
00273                 *response = create_status_response(request, rv);
00274                 return BS_OK;
00275         }
00276         else if (streq(request->operation, "add_user")) {
00277                 if (request->input->num_parts != 2) return BS_ERROR;
00278                 rv = add_user(request->input->parts[0]->data,
00279                                 request->input->parts[1]->data);
00280                 *response = create_status_response(request, rv);
00281                 return BS_OK;   
00282         }
00283         else if (streq(request->operation, "remove_user")) {
00284                 if (request->input->num_parts != 1) return BS_ERROR;
00285                 rv = remove_user(request->input->parts[0]->data);
00286                 *response = create_status_response(request, rv);
00287                 return BS_OK;           
00288         }
00289         
00290         return BS_NO_SERVICE;                   
00291 }
00292 
00293 
00294 /* Final declaration of the bs_module struct: */
00295 bs_module bsmod_symtable = {
00296         /* The major and minor version of the API used by this module: */
00297         0,
00298         0,
00299         
00300         /* The major and minor version of this module: */
00301         0,
00302         1,
00303         
00304         /* The name, author, date and copyright information: */
00305         "password module",
00306         "M.A.Hartman",
00307         "may 9, 2007",
00308         "(c) 2007, M.A.Hartman. See distributed LICENSE file for more information.",
00309         "A module which offers password functions. ",
00310         
00311         /* Init and cleanup routines: */
00312         bsmod_password_init,
00313         bsmod_password_cleanup,
00314         
00315         /* Service request handling function: */
00316         bsmod_password_handle_service,
00317         NULL,
00318         "bsmod_password.wsdl"
00319 };
00320 

Generated on Tue Jul 17 09:50:52 2007 for Bio-SPHERE by  doxygen 1.5.1