Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

session.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: session.c,v 1.36 2006/04/06 14:02:22 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <sys/types.h>
00013 #include <sys/stat.h>
00014 #include <sys/time.h>
00015 #include <stdlib.h>
00016 #include <time.h>
00017 #include <unistd.h>
00018 #include <fcntl.h>
00019 #ifdef HAVE_LIBOPENSSL
00020 #include <openssl/hmac.h>
00021 #include <openssl/evp.h>
00022 #include <openssl/rand.h>
00023 #include <klone/ccipher.h>
00024 #endif /* HAVE_LIBOPENSSL */
00025 #include <u/libu.h>
00026 #include <klone/session.h>
00027 #include <klone/request.h>
00028 #include <klone/response.h>
00029 #include <klone/vars.h>
00030 #include <klone/utils.h>
00031 #include <klone/ses_prv.h>
00032 #include <klone/codecs.h>
00033 
00034 enum { DEFAULT_SESSION_EXPIRATION = 60*20 }; /* 20 minutes */
00035 static const char SID_NAME[] = "klone_sid";
00036 
00037 struct save_cb_params_s
00038 {
00039     session_t *ss;
00040     io_t *io;
00041 };
00042 
00043 typedef struct save_cb_params_s save_cb_params_t;
00044 
00045 int session_module_term(session_opt_t *so)
00046 {
00047     U_FREE(so);
00048 
00049     return 0;
00050 }
00051 
00052 int session_module_init(u_config_t *config, session_opt_t **pso)
00053 {
00054     session_opt_t *so = NULL;
00055     u_config_t *c = NULL;
00056     const char *v;
00057     int max_age;
00058 
00059     dbg_err_if (config == NULL);
00060     dbg_err_if (pso == NULL);
00061 
00062     so = u_zalloc(sizeof(session_opt_t));
00063     dbg_err_if(so == NULL);
00064 
00065     /* defaults values */
00066     so->type = SESSION_TYPE_FILE;
00067     so->max_age = DEFAULT_SESSION_EXPIRATION;
00068     so->compress = 0;
00069     so->encrypt = 0;
00070 
00071     if(!u_config_get_subkey(config, "session", &c))
00072     {
00073         /* no 'session' subsection, defaults will be used */
00074 
00075         /* set session type */
00076         if((v = u_config_get_subkey_value(c, "type")) != NULL)
00077         {
00078             if(!strcasecmp(v, "memory")) {
00079                 so->type = SESSION_TYPE_MEMORY;
00080             } else if(!strcasecmp(v, "file")) {
00081                 so->type = SESSION_TYPE_FILE;
00082 #ifdef HAVE_LIBOPENSSL
00083             } else if(!strcasecmp(v, "client")) {
00084                 so->type = SESSION_TYPE_CLIENT;
00085 #endif
00086             } else
00087                warn_err("config error: bad session type (typo or missing "
00088                         "library)");
00089         }
00090 
00091         /* set max_age */
00092         if((v = u_config_get_subkey_value(c, "max_age")) != NULL)
00093             max_age = MAX(atoi(v) * 60, 60); /* min value: 1 min */
00094 
00095         /* set compression flag */
00096         dbg_err_if(u_config_get_subkey_value_b(c, "compress", 0,
00097             &so->compress));
00098 
00099         /* set encryption flag */
00100         dbg_err_if(u_config_get_subkey_value_b(c, "encrypt", 0, &so->encrypt));
00101 
00102 #ifndef HAVE_LIBZ
00103         if(so->compress)
00104             warn_err("config error: compression is enabled but libz is not "
00105                      "linked");
00106 #endif
00107 
00108 #ifndef HAVE_LIBOPENSSL
00109         if(so->encrypt)
00110             warn_err("config error: encryption is enabled but OpenSSL is not "
00111                      "linked");
00112 #else
00113         /* init cipher EVP algo, the random key and IV */
00114         so->cipher = EVP_aes_256_cbc(); /* use AES-256 in CBC mode */
00115 
00116         EVP_add_cipher(so->cipher);
00117 
00118         /* key and iv for client-side session */
00119         dbg_err_if(!RAND_bytes(so->cipher_key, CIPHER_KEY_SIZE));
00120         dbg_err_if(!RAND_pseudo_bytes(so->cipher_iv, CIPHER_IV_SIZE));
00121 
00122         /* create a random key and iv to crypt the KLONE_CIPHER_KEY variable */
00123         dbg_err_if(!RAND_bytes(so->session_key, CIPHER_KEY_SIZE));
00124         dbg_err_if(!RAND_pseudo_bytes(so->session_iv, CIPHER_IV_SIZE));
00125 
00126 #endif
00127     } /* if "session" exists */
00128 
00129     /* per-type configuration init */
00130     if(so->type == SESSION_TYPE_MEMORY)
00131         warn_err_ifm(session_mem_module_init(c, so), 
00132             "in-memory session engine init error");
00133     else if(so->type == SESSION_TYPE_FILE)
00134         warn_err_ifm(session_file_module_init(c, so), 
00135             "file session engine init error");
00136 #ifdef HAVE_LIBOPENSSL
00137     else if(so->type == SESSION_TYPE_CLIENT)
00138         warn_err_ifm(session_client_module_init(c, so),
00139             "client-side session engine init error");
00140 #endif
00141 
00142     *pso = so;
00143 
00144     return 0;
00145 err:
00146     U_FREE(so);
00147     return ~0;
00148 }
00149 
00150 int session_prv_calc_maxsize(var_t *v, void *p)
00151 {
00152     const char *value = NULL;
00153     size_t *psz = (size_t*)p;
00154 
00155     dbg_err_if (v == NULL);
00156     dbg_err_if (var_get_name(v) == NULL);
00157     dbg_err_if (psz == NULL);
00158 
00159 #ifdef HAVE_LIBOPENSSL
00160     if(*psz == 0)
00161     {   /* first time here */
00162         *psz = CODEC_CIPHER_BLOCK_SIZE;
00163     }
00164 #endif
00165 
00166     /* name= */
00167     *psz += 3 * strlen(var_get_name(v)) + 3;
00168 
00169     /* value */
00170     if((value = var_get_value(v)) != NULL)
00171         *psz += 3 * strlen(value) + 1; /* worse case (i.e. longest string) */
00172 
00173     return 0;
00174 err:
00175     return ~0;
00176 }
00177 
00178 int session_prv_load_from_buf(session_t *ss, char *buf, size_t size)
00179 {
00180     io_t *io = NULL;
00181 
00182     dbg_err_if (ss == NULL);
00183     dbg_err_if (buf == NULL);
00184 
00185     /* build an io_t around the buffer */
00186     dbg_err_if(io_mem_create(buf, size, 0, &io));
00187 
00188     /* load data */
00189     dbg_err_if(session_prv_load_from_io(ss, io));
00190 
00191     io_free(io);
00192 
00193     return 0;
00194 err:
00195     if(io)
00196         io_free(io);
00197     return ~0;
00198 }
00199 
00200 int session_prv_save_to_buf(session_t *ss, char **pbuf, size_t *psz)
00201 {
00202     io_t *io = NULL;
00203     char *buf = NULL;
00204     size_t sz = 0;
00205 
00206     dbg_err_if (ss == NULL);
00207     dbg_err_if (pbuf == NULL);
00208     dbg_err_if (psz == NULL);
00209  
00210     /* calc the maximum session data size (exact calc requires url encoding and
00211        codec transformation knowledge) */
00212     vars_foreach(ss->vars, session_prv_calc_maxsize, (void*)&sz);
00213 
00214     /* alloc a big-enough block to save the session data */
00215     buf = u_malloc(sz);
00216     dbg_err_if(buf == NULL);
00217 
00218     /* create a big-enough in-memory io object */
00219     dbg_err_if(io_mem_create(buf, sz, 0, &io));
00220 
00221     /* save the session to the in-memory io */
00222     dbg_err_if(session_prv_save_to_io(ss, io));
00223 
00224     /* remove all codecs to get the right size of 'buf'. we need to remove 
00225        the codecs because some of them buffer data until last codec->flush() 
00226        is called (and it's not possible to flush codecs without removing them */
00227     dbg_err_if(io_codecs_remove(io));
00228 
00229     /* get the number of bytes written to the io (so to 'buf') */
00230     sz = io_tell(io);
00231 
00232     io_free(io);
00233     io = NULL;
00234 
00235     *pbuf = buf;
00236     *psz = sz;
00237 
00238     return 0;
00239 err:
00240     if(io)
00241         io_free(io);
00242     U_FREE(buf);
00243     return ~0;
00244 }
00245 
00246 static int session_is_good_id(const char *id)
00247 {
00248     const char *p;
00249     size_t len;
00250 
00251     dbg_return_if (id == NULL, 0);
00252 
00253     dbg_ifb((len = strlen(id)) != SESSION_ID_LENGTH)
00254         return 0; /* wrong length */
00255 
00256     for(p = id; len; --len, ++p)
00257     {
00258         /* if is hex */
00259         if(! ((*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f') || 
00260               (*p >= '0' && *p <= '9')) )
00261         return 0; /* not safe */
00262     }
00263 
00264     return 1; /* good */
00265 }
00266 
00267 static int session_set_filename(session_t *ss)
00268 {
00269     addr_t *addr = NULL;
00270 
00271     dbg_err_if(strlen(ss->id) == 0);
00272 
00273     dbg_err_if((addr = request_get_addr(ss->rq)) == NULL);
00274     switch(addr->type)
00275     {
00276     case ADDR_IPV4:
00277         dbg_err_if(u_path_snprintf(ss->filename, U_FILENAME_MAX, 
00278             U_PATH_SEPARATOR, "%s/klone_sess_%s_%lu", ss->so->path, ss->id, 
00279             addr->sa.sin.sin_addr));
00280         break;
00281     case ADDR_IPV6:
00282         /* FIXME: add ipv6 address in session filename */
00283         dbg_err_if(u_path_snprintf(ss->filename, U_FILENAME_MAX, 
00284             U_PATH_SEPARATOR, "%s/klone_sess_%s", ss->so->path, ss->id));
00285         break;
00286 #ifdef OS_UNIX
00287     case ADDR_UNIX:
00288         /* FIXME: add unix address in session filename */
00289         dbg_err_if(u_path_snprintf(ss->filename, U_FILENAME_MAX, 
00290             U_PATH_SEPARATOR, "%s/klone_sess_%s", ss->so->path, ss->id));
00291         break;
00292 #endif
00293     }
00294 
00295     return 0;
00296 err:
00297     return 0;
00298 }
00299 
00300 static int session_gen_id(session_t *ss)
00301 {
00302     enum { BUFSZ = 256 };
00303     char buf[BUFSZ];
00304     struct timeval tv;
00305 
00306     dbg_err_if (ss == NULL);
00307     
00308     /* gen a new one */
00309     gettimeofday(&tv, NULL);
00310 
00311     dbg_err_if(u_snprintf(buf, BUFSZ, "%lu%d%lu%d", tv.tv_sec, getpid(), 
00312         tv.tv_usec, rand()));
00313 
00314     /* return the md5 (in hex) buf */
00315     dbg_err_if(u_md5(buf, strlen(buf), ss->id));
00316 
00317     /* remove previous sid if any */ 
00318     dbg_err_if(response_set_cookie(ss->rs, SID_NAME, NULL, 0, NULL, NULL, 0));
00319 
00320     /* set the cookie ID */
00321     dbg_err_if(response_set_cookie(ss->rs, SID_NAME, ss->id, 0, NULL, 
00322         NULL, 0));
00323 
00324     return 0;
00325 err:
00326     return ~0;
00327 }
00328 
00329 int session_priv_set_id(session_t *ss, const char *sid)
00330 {
00331     /* set or generate a session id */
00332     if(sid && session_is_good_id(sid))
00333     {
00334         dbg_err_if(u_snprintf(ss->id, SESSION_ID_BUFSZ, "%s", sid));
00335         ss->id[SESSION_ID_BUFSZ-1] = 0;
00336     } else
00337         dbg_err_if(session_gen_id(ss));
00338 
00339     /* set the filename accordingly */
00340     dbg_err_if(session_set_filename(ss));
00341 
00342     return 0;
00343 err:
00344     return ~0;
00345 }
00346 
00353 int session_load(session_t *ss)
00354 {
00355     dbg_return_if (ss == NULL, ~0);
00356     dbg_return_if (ss->load == NULL, ~0);
00357 
00358     return ss->load(ss);
00359 }
00360 
00361 int session_save(session_t *ss)
00362 {
00363     dbg_err_if (ss == NULL);
00364     dbg_err_if (ss->save == NULL);
00365 
00366     if(vars_count(ss->vars) == 0)
00367         return 0; /* nothing to save */
00368 
00369     if(!strlen(ss->id))
00370     {
00371         /* generate a new SID and set session filename accordingly */
00372         dbg_err_if(session_priv_set_id(ss, NULL)); 
00373     }
00374 
00375     return ss->save(ss);
00376 err:
00377     return ~0;
00378 }
00379 
00380 int session_remove(session_t *ss)
00381 {
00382     dbg_return_if (ss == NULL, ~0);
00383     dbg_return_if (ss->remove == NULL, ~0);
00384 
00385     ss->removed = 1;
00386 
00387     return ss->remove(ss);
00388 }
00389 
00390 int session_prv_init(session_t *ss, request_t *rq, response_t *rs)
00391 {
00392     const char *sid;
00393 
00394     dbg_err_if (ss == NULL);
00395     dbg_err_if (rq == NULL);
00396     dbg_err_if (rs == NULL);
00397     
00398     dbg_err_if(vars_create(&ss->vars));
00399 
00400     ss->rq = rq;
00401     ss->rs = rs;
00402 
00403     /* if the client has a SID set and it's a good one then use it */
00404     sid = request_get_cookie(ss->rq, SID_NAME);
00405     if(sid)
00406         dbg_err_if(session_priv_set_id(ss, sid));
00407 
00408     return 0;
00409 err:
00410     return ~0;
00411 }
00412 
00413 int session_prv_load_from_io(session_t *ss, io_t *io)
00414 {
00415     u_string_t *line = NULL;
00416     var_t *v = NULL;
00417     codec_t *unzip = NULL, *decrypt = NULL;
00418     unsigned char key[CODEC_CIPHER_KEY_SIZE];
00419     size_t ksz;
00420 
00421     dbg_return_if (ss == NULL, ~0);
00422     dbg_return_if (io == NULL, ~0);
00423 
00424 #ifdef HAVE_LIBOPENSSL
00425     if(ss->so->encrypt)
00426     {
00427         dbg_err_if(codec_cipher_create(CIPHER_DECRYPT, ss->so->cipher, 
00428             ss->so->cipher_key, ss->so->cipher_iv, &decrypt)); 
00429         dbg_err_if(io_codec_add_tail(io, decrypt));
00430         decrypt = NULL; /* io_t owns it after io_codec_add_tail */
00431     }
00432 #else
00433     u_unused_args(key, ksz);
00434 #endif
00435 
00436 #ifdef HAVE_LIBZ
00437     if(ss->so->compress)
00438     {
00439         dbg_err_if(codec_gzip_create(GZIP_UNCOMPRESS, &unzip));
00440         dbg_err_if(io_codec_add_tail(io, unzip));
00441         unzip = NULL; /* io_t owns it after io_codec_add_tail */
00442     }
00443 #endif
00444 
00445     dbg_err_if(u_string_create(NULL, 0, &line));
00446 
00447     while(u_getline(io, line) == 0)
00448     {
00449         if(u_string_len(line))
00450         {
00451             dbg_err_if(vars_add_urlvar(ss->vars, u_string_c(line), &v));
00452 
00453 #ifdef HAVE_LIBOPENSSL
00454             if(!strcmp(var_get_name(v), "KLONE_CIPHER_KEY"))
00455             {
00456                 /* decrypt key and save it to key */
00457                 memset(key, 0, sizeof(key));
00458                 dbg_ifb(u_cipher_decrypt(EVP_aes_256_cbc(), ss->so->session_key,
00459                     ss->so->session_iv, key, &ksz, 
00460                     var_get_value(v), var_get_value_size(v)))
00461                 {
00462                     v = vars_get(ss->vars, "KLONE_CIPHER_KEY");
00463                     vars_del(ss->vars, v);
00464                 } else {
00465                     /* save it to the var list */
00466                     dbg_err_if(var_set_bin_value(v, key, ksz));
00467                 }
00468             }
00469 #endif
00470         }
00471     }
00472 
00473     /* remove set codecs and flush */
00474     io_codecs_remove(io);
00475 
00476     u_string_free(line);
00477 
00478     return 0;
00479 err:
00480     if(io)
00481         io_codecs_remove(io);
00482     if(decrypt)
00483         codec_free(decrypt);
00484     if(unzip)
00485         codec_free(unzip);
00486     if(line)
00487         u_string_free(line);
00488     return ~0;
00489 }
00490 
00491 int session_free(session_t *ss)
00492 {
00493     if (ss)
00494     { 
00495         if(!ss->removed)
00496             dbg_if(session_save(ss));
00497 
00498         /* driver cleanup */
00499         dbg_if(ss->term(ss));
00500 
00501         if(ss->vars)
00502             vars_free(ss->vars);
00503 
00504         U_FREE(ss);
00505     }
00506 
00507     return 0;
00508 }
00509 
00519 vars_t *session_get_vars(session_t *ss)
00520 {
00521     dbg_return_if (ss == NULL, NULL);
00522 
00523     return ss->vars;
00524 }
00525 
00537 const char *session_get(session_t *ss, const char *name)
00538 {
00539     var_t *v;
00540 
00541     dbg_return_if (ss == NULL, NULL);
00542     dbg_return_if (name == NULL, NULL);
00543     
00544     v = vars_get(ss->vars, name);
00545     return v ? var_get_value(v): NULL;
00546 }
00547 
00559 int session_set(session_t *ss, const char *name, const char *value)
00560 {
00561     var_t *v = NULL;
00562 
00563     dbg_err_if (ss == NULL);
00564     dbg_err_if (name == NULL);
00565     dbg_err_if (value == NULL);
00566     dbg_err_if (strlen(name) == 0);
00567 
00568     if((v = vars_get(ss->vars, name)) == NULL)
00569     {
00570         /* add a new session variable */
00571         dbg_err_if(var_create(name, value, &v));
00572 
00573         dbg_err_if(vars_add(ss->vars, v));
00574     } else {
00575         /* update an existing var */
00576         dbg_ifb(var_set_value(v, value))
00577             return ~0;
00578     }
00579 
00580     return 0;
00581 err:
00582     if(v)
00583         var_free(v);
00584     return ~0;
00585 }
00586 
00598 int session_age(session_t *ss)
00599 {
00600     time_t now;
00601 
00602     dbg_return_if (ss == NULL, -1);
00603 
00604     now = time(0);
00605 
00606     /* ss->mtime must has been set into session_X_create funcs */
00607     return (int)(now - ss->mtime); /* in seconds */
00608 }
00609 
00619 int session_clean(session_t *ss)
00620 {
00621     var_t *v = NULL;
00622 
00623     dbg_err_if (ss == NULL);
00624 
00625     while((v = vars_getn(ss->vars, 0)) != NULL)
00626     {
00627         dbg_err_if(vars_del(ss->vars, v));
00628         var_free(v);
00629     }
00630 
00631     return 0;
00632 err:
00633     return ~0;
00634 }
00635 
00648 int session_del(session_t *ss, const char *name)
00649 {
00650     var_t *v = NULL;
00651 
00652     dbg_err_if (ss == NULL);
00653     dbg_err_if (name == NULL);
00654     
00655     dbg_err_if((v = vars_get(ss->vars, name)) == NULL);
00656     dbg_err_if(vars_del(ss->vars, v));
00657     var_free(v);
00658 
00659     return 0;
00660 err:
00661     return ~0;
00662 }
00663 
00664 int session_prv_save_to_io(session_t *ss, io_t *out)
00665 {
00666     save_cb_params_t prm; 
00667     codec_t *zip = NULL, *cencrypt = NULL;
00668 
00669     dbg_err_if (ss == NULL);
00670     dbg_err_if (out == NULL);
00671 
00672 #ifdef HAVE_LIBZ
00673     if(ss->so->compress)
00674     {
00675         dbg_err_if(codec_gzip_create(GZIP_COMPRESS, &zip));
00676         dbg_err_if(io_codec_add_tail(out, zip));
00677         zip = NULL; /* io_t owns it after io_codec_add_tail */
00678     }
00679 #endif
00680 
00681 #ifdef HAVE_LIBOPENSSL
00682     if(ss->so->encrypt)
00683     {
00684         dbg_err_if(codec_cipher_create(CIPHER_ENCRYPT, ss->so->cipher, 
00685             ss->so->cipher_key, ss->so->cipher_iv, &cencrypt));
00686         dbg_err_if(io_codec_add_tail(out, cencrypt));
00687         cencrypt = NULL; /* io_t owns it after io_codec_add_tail */
00688     }
00689 #endif
00690 
00691     /* pass io and session poiters to the callback function */
00692     prm.io = out;
00693     prm.ss = ss;
00694 
00695     vars_foreach(ss->vars, session_prv_save_var, (void*)&prm);
00696 
00697     /* remove all codecs and flush */
00698     io_codecs_remove(out);
00699 
00700     return 0;
00701 err:
00702     if(out)
00703         io_codecs_remove(out);
00704     if(zip)
00705         codec_free(zip);
00706     if(cencrypt)
00707         codec_free(cencrypt);
00708     return ~0;
00709 }
00710 
00711 /* save a var_t (text or binary) to the session io_t */
00712 int session_prv_save_var(var_t *v, void *vp)
00713 {
00714     enum { NAMESZ = 256, VALSZ = 4096 };
00715     char sname[NAMESZ], svalue[VALSZ];
00716     char *uname = sname, *uvalue = svalue;
00717     save_cb_params_t *pprm = (save_cb_params_t*)vp;
00718     /* encrypted key buffer */
00719     unsigned char ekey[CODEC_CIPHER_KEY_SIZE + CODEC_CIPHER_BLOCK_SIZE + 1]; 
00720     size_t eksz, nsz, vsz;
00721     int rc = ~0;
00722 
00723     dbg_err_if (v == NULL);
00724     /* dbg_err_if (vp == NULL); */
00725 
00726     /* buffers must be at least three times the src data to URL-encode  */
00727     nsz = 1 + 3 * strlen(var_get_name(v));  /* name buffer size  */
00728     vsz = 1 + 3 * var_get_value_size(v);    /* value buffer size */
00729 
00730 #ifdef HAVE_LIBOPENSSL
00731     vsz += CODEC_CIPHER_BLOCK_SIZE; /* encryption may enlarge the content up 
00732                                        to CODEC_CIPHER_BLOCK_SIZE -1         */
00733 #else
00734     u_unused_args(ekey, eksz);
00735 #endif
00736 
00737     /* if the buffer on the stack is too small alloc a bigger one */
00738     if(NAMESZ <= nsz)
00739         dbg_err_if((uname = u_zalloc(nsz)) == NULL);
00740 
00741     /* url encode name */
00742     dbg_err_if(u_urlncpy(uname, var_get_name(v), strlen(var_get_name(v)), 
00743         URLCPY_ENCODE) <= 0);
00744 
00745     if(var_get_value(v))
00746     {
00747         /* if the buffer on the stack is too small alloc a bigger one */
00748         if(VALSZ <= vsz)
00749             dbg_err_if((uvalue = u_zalloc(vsz)) == NULL);
00750 
00751 #ifdef HAVE_LIBOPENSSL
00752         if(!strcmp(var_get_name(v), "KLONE_CIPHER_KEY"))
00753         {
00754             /* encrypt key and save it to ekey */
00755             dbg_err_if(u_cipher_encrypt(EVP_aes_256_cbc(), 
00756                 pprm->ss->so->session_key, pprm->ss->so->session_iv, 
00757                 ekey, &eksz, var_get_value(v), var_get_value_size(v)));
00758 
00759             /* save it to the var list */
00760             dbg_err_if(var_set_bin_value(v, ekey, eksz));
00761         }
00762 #endif
00763 
00764         dbg_err_if(u_urlncpy(uvalue, var_get_value(v), var_get_value_size(v), 
00765             URLCPY_ENCODE) <= 0);
00766 
00767         dbg_err_if(io_printf(pprm->io, "%s=%s\n", uname, uvalue) < 0);
00768     } else 
00769         dbg_err_if(io_printf(pprm->io, "%s=\n", uname) < 0);
00770 
00771     rc = 0; /* success */
00772 err:
00773     /* free heap buffers */
00774     if(uname && uname != sname)
00775         U_FREE(uname);
00776 
00777     if(uvalue && uvalue != svalue)
00778         U_FREE(uvalue);
00779 
00780     return rc;
00781 }
00782 
00783 int session_create(session_opt_t *so, request_t *rq, response_t *rs, 
00784     session_t **pss)
00785 {
00786     session_t *ss = NULL;
00787 
00788     dbg_err_if (so == NULL);
00789     dbg_err_if (rq == NULL);
00790     dbg_err_if (rs == NULL);
00791     dbg_err_if (pss == NULL);
00792 
00793     switch(so->type)
00794     {
00795     case SESSION_TYPE_FILE:
00796         dbg_err_if(session_file_create(so, rq, rs, &ss));
00797         break;
00798     case SESSION_TYPE_MEMORY:
00799         dbg_err_if(session_mem_create(so, rq, rs, &ss));
00800         break;
00801 #ifdef HAVE_LIBOPENSSL
00802     case SESSION_TYPE_CLIENT:
00803         dbg_err_if(session_client_create(so, rq, rs, &ss));
00804         break;
00805 #endif
00806     default:
00807         warn_err("bad session type");
00808     }
00809 
00810     /* may fail if the session does not exist */
00811     session_load(ss);
00812 
00813     dbg_ifb(session_age(ss) > so->max_age)
00814     {
00815         session_clean(ss);  /* remove all session variables */
00816         session_remove(ss); /* remove the session itself    */
00817     }
00818 
00819     *pss = ss;
00820 
00821     return 0;
00822 err:
00823     if(ss)
00824         session_free(ss);
00825     return ~0;
00826 }
00827 

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved