LCOV - code coverage report
Current view: top level - zxid - zxiduser.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 109 189 57.7 %
Date: 2010-12-19 Functions: 6 6 100.0 %
Branches: 82 220 37.3 %

           Branch data     Line data    Source code
       1                 :            : /* zxiduser.c  -  Handwritten functions for SP user local account management
       2                 :            :  * Copyright (c) 2009-2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 2007-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
       4                 :            :  * Author: Sampo Kellomaki (sampo@iki.fi)
       5                 :            :  * This is confidential unpublished proprietary source code of the author.
       6                 :            :  * NO WARRANTY, not even implied warranties. Contains trade secrets.
       7                 :            :  * Distribution prohibited unless authorized in writing.
       8                 :            :  * Licensed under Apache License 2.0, see file COPYING.
       9                 :            :  * $Id: zxiduser.c,v 1.18 2009-11-29 12:23:06 sampo Exp $
      10                 :            :  *
      11                 :            :  * 12.10.2007, created --Sampo
      12                 :            :  * 7.10.2008,  added documentation --Sampo
      13                 :            :  * 14.11.2009, added yubikey (yubico.com) support --Sampo
      14                 :            :  * 23.9.2010,  added delegation support --Sampo
      15                 :            :  */
      16                 :            : 
      17                 :            : #include "platform.h"  /* for dirent.h */
      18                 :            : 
      19                 :            : #include <sys/types.h>
      20                 :            : #include <sys/stat.h>
      21                 :            : #include <fcntl.h>
      22                 :            : #include <string.h>
      23                 :            : #include <stdio.h>
      24                 :            : #include <errno.h>
      25                 :            : 
      26                 :            : #ifdef USE_OPENSSL
      27                 :            : #include <openssl/des.h>
      28                 :            : #endif
      29                 :            : 
      30                 :            : #include "errmac.h"
      31                 :            : #include "zxid.h"
      32                 :            : #include "zxidutil.h"
      33                 :            : #include "zxidconf.h"
      34                 :            : #include "yubikey.h"   /* from libyubikey-1.5 */
      35                 :            : #include "c/zx-sa-data.h"
      36                 :            : 
      37                 :            : /*() Parse a line from .mni and form a NameID, unless there is mniptr */
      38                 :            : 
      39                 :            : /* Called by:  zxid_check_fed, zxid_get_user_nameid */
      40                 :            : zxid_nid* zxid_parse_mni(zxid_conf* cf, char* buf, char** pmniptr)
      41                 :       1226 : {
      42                 :            :   zxid_nid* nameid;
      43                 :            :   char* p;
      44                 :       1226 :   char* idpent = 0;
      45                 :       1226 :   char* spqual = 0;
      46                 :       1226 :   char* nid = 0;
      47                 :       1226 :   char* mniptr = 0;
      48                 :            : 
      49                 :       1226 :   p = strchr(buf, '|');
      50         [ +  - ]:       1226 :   if (p) {
      51                 :       1226 :     *p = 0;
      52                 :       1226 :     idpent = ++p;
      53                 :       1226 :     p = strchr(p, '|');
      54         [ +  - ]:       1226 :     if (p) {
      55                 :       1226 :       *p = 0;
      56                 :       1226 :       spqual = ++p;
      57                 :       1226 :       p = strchr(p, '|');
      58         [ +  - ]:       1226 :       if (p) {
      59                 :       1226 :         *p = 0;
      60                 :       1226 :         nid = ++p;
      61                 :       1226 :         p = strchr(p, '|');
      62         [ +  + ]:       1226 :         if (p) {
      63                 :       1172 :           *p = 0;
      64                 :       1172 :           mniptr = ++p;
      65                 :       1172 :           p = strchr(p, '|');
      66         [ -  + ]:       1172 :           if (p)
      67                 :          0 :             *p = 0;
      68                 :            :         }
      69                 :            :       }
      70                 :            :     }
      71                 :            :   }
      72                 :            :   
      73   [ +  +  -  + ]:       1226 :   if (mniptr && *mniptr) {
      74         [ #  # ]:          0 :     if (pmniptr)
      75                 :          0 :       *pmniptr = mniptr;
      76                 :          0 :     return 0;
      77                 :            :   }
      78                 :            :   
      79                 :       1226 :   nameid = zx_NEW_sa_NameID(cf->ctx,0);
      80         [ +  - ]:       1226 :   if (*buf)              nameid->Format = zx_dup_attr(cf->ctx, &nameid->gg, zx_Format_ATTR, buf);
      81   [ +  -  +  - ]:       1226 :   if (idpent && *idpent) nameid->NameQualifier = zx_dup_attr(cf->ctx, &nameid->gg, zx_NameQualifier_ATTR, idpent);
      82   [ +  -  +  - ]:       1226 :   if (spqual && *spqual) nameid->SPNameQualifier = zx_dup_attr(cf->ctx, &nameid->gg, zx_SPNameQualifier_ATTR, spqual);
      83   [ +  -  +  - ]:       1226 :   if (nid && *nid)       zx_add_content(cf->ctx, &nameid->gg, zx_dup_str(cf->ctx, nid));
      84                 :       1226 :   return nameid;
      85                 :            : }
      86                 :            : 
      87                 :            : /*() Formulate NameID based directory name for the user. qualif is usually
      88                 :            :  * the IdP Entity ID. It is important to separate between same nid
      89                 :            :  * issued by different IdP. The result is "returned" by modifying
      90                 :            :  * sha1_name buffer, which MUST be at least 28 characters long. */
      91                 :            : 
      92                 :            : /* Called by:  zxid_get_user_nameid, zxid_put_user, zxid_ses_to_pool x2, zxid_user_change_nameid */
      93                 :            : void zxid_user_sha1_name(zxid_conf* cf, struct zx_str* qualif, struct zx_str* nid, char* sha1_name)
      94                 :        168 : {
      95                 :            :   struct zx_str* ss;
      96         [ -  + ]:        168 :   if (!nid) {
      97                 :          0 :     ZERO(sha1_name, 28);
      98                 :          0 :     return;
      99                 :            :   }
     100         [ +  + ]:        168 :   if (qualif) {
     101                 :        161 :     ss = zx_strf(cf->ctx, "%.*s|%.*s", qualif->len, qualif->s, nid->len, nid->s);
     102                 :        161 :     sha1_safe_base64(sha1_name, ss->len, ss->s);
     103                 :        161 :     zx_str_free(cf->ctx, ss);
     104                 :            :   } else {
     105                 :          7 :     sha1_safe_base64(sha1_name, nid->len, nid->s);
     106                 :            :   }
     107                 :        168 :   sha1_name[27] = 0;
     108                 :            : }
     109                 :            : 
     110                 :            : /*() Locate user file using a NameID, which may be old or current. If old,
     111                 :            :  * chase the MNIptr fields until current is found. Mainly used to support MNI. */
     112                 :            : 
     113                 :            : /* Called by:  zxid_sp_mni_redir, zxid_sp_mni_soap, zxid_sp_slo_redir, zxid_sp_slo_soap */
     114                 :            : zxid_nid* zxid_get_user_nameid(zxid_conf* cf, zxid_nid* oldnid)
     115                 :          2 : {
     116                 :            :   char sha1_name[28];
     117                 :            :   char* buf;
     118                 :            :   char* mniptr;
     119                 :          2 :   int iter = 1000;
     120                 :            :   zxid_nid* nameid;
     121                 :            :   
     122         [ -  + ]:          2 :   if (!cf->user_local)
     123                 :          0 :     return oldnid;
     124                 :            :   
     125   [ +  -  +  -  :          2 :   zxid_user_sha1_name(cf, &oldnid->NameQualifier->g, ZX_GET_CONTENT(oldnid), sha1_name);
                   +  - ]
     126                 :          2 :   buf = ZX_ALLOC(cf->ctx, ZXID_MAX_USER);
     127                 :          2 :   mniptr = sha1_name;
     128                 :            : 
     129   [ +  -  +  -  :          4 :   while (--iter && mniptr && *mniptr) {
                   +  - ]
     130                 :          2 :     read_all(ZXID_MAX_USER, buf, (const char*)__FUNCTION__, 1, "%s" ZXID_USER_DIR "%s/.mni", cf->path, mniptr);
     131                 :          2 :     nameid = zxid_parse_mni(cf, buf, &mniptr);
     132         [ +  - ]:          2 :     if (nameid)
     133                 :          2 :       return nameid;
     134   [ #  #  #  # ]:          0 :     if (!mniptr || !strcmp(mniptr, sha1_name)) {
     135         [ #  # ]:          0 :       ERR("Infinite loop in MNI changed NameIDs in user database mniptr(%s) iter(%d)", STRNULLCHK(mniptr), iter);
     136                 :          0 :       return 0;
     137                 :            :     }
     138                 :            :   }
     139   [ #  #  #  #  :          0 :   ERR("Too many mniptr indirections for oldnid(%.*s)", ZX_GET_CONTENT_LEN(oldnid), ZX_GET_CONTENT_S(oldnid));
          #  #  #  #  #  
                #  #  # ]
     140                 :          0 :   return 0;
     141                 :            : }
     142                 :            : 
     143                 :            : /*() Change a NameID to newnym. Old NameID's user entry is rewritten to have mniptr */
     144                 :            : 
     145                 :            : /* Called by:  zxid_mni_do */
     146                 :            : void zxid_user_change_nameid(zxid_conf* cf, zxid_nid* oldnid, struct zx_str* newnym)
     147                 :          1 : {
     148                 :            :   char sha1_name[28];
     149                 :          1 :   zxid_user_sha1_name(cf, &oldnid->NameQualifier->g, newnym, sha1_name);
     150                 :          1 :   zxid_put_user(cf, &oldnid->Format->g, &oldnid->NameQualifier->g, &oldnid->SPNameQualifier->g, newnym, 0);
     151   [ +  -  +  -  :          1 :   zxid_put_user(cf, &oldnid->Format->g, &oldnid->NameQualifier->g, &oldnid->SPNameQualifier->g, ZX_GET_CONTENT(oldnid), sha1_name);
                   +  - ]
     152                 :          1 : }
     153                 :            : 
     154                 :            : /*() Create new user object in file system. Will create user diretory (but not
     155                 :            :  * its subdirectories).
     156                 :            :  * See also zxid_ses_to_pool() */
     157                 :            : 
     158                 :            : /* Called by:  zxid_sp_sso_finalize, zxid_user_change_nameid x2, zxid_wsp_validate_env */
     159                 :            : int zxid_put_user(zxid_conf* cf, struct zx_str* nidfmt, struct zx_str* idpent, struct zx_str* spqual, struct zx_str* idpnid, char* mniptr)
     160                 :         43 : {
     161                 :            :   char sha1_name[28];
     162                 :            :   char dir[ZXID_MAX_BUF];
     163                 :            :   char* buf;
     164                 :            :   
     165         [ -  + ]:         43 :   if (!cf->user_local)
     166                 :          0 :     return 0;
     167                 :            :   
     168         [ -  + ]:         43 :   if (!idpnid) {
     169                 :          0 :     ERR("Missing NameID %p", idpent);
     170                 :          0 :     return 0;
     171                 :            :   }
     172                 :            :   
     173                 :         43 :   zxid_user_sha1_name(cf, idpent, idpnid, sha1_name);
     174                 :         43 :   name_from_path(dir, sizeof(dir), "%s" ZXID_USER_DIR "%s", cf->path, sha1_name);
     175   [ +  +  -  + ]:         43 :   if (MKDIR(dir, 0777) && errno != EEXIST) {
     176                 :          0 :     perror("mkdir for user");
     177                 :          0 :     ERR("Creating user directory(%s) failed", dir);
     178                 :          0 :     return 0;
     179                 :            :   }
     180                 :            :   
     181                 :         43 :   buf = ZX_ALLOC(cf->ctx, ZXID_MAX_USER);
     182   [ +  +  +  +  :         43 :   write_all_path_fmt("put_user", ZXID_MAX_USER, buf,
          +  +  +  +  +  
             +  +  -  +  
                      - ]
     183                 :            :                      "%s" ZXID_USER_DIR "%s/.mni", cf->path, sha1_name,
     184                 :            :                      "%.*s|%.*s|%.*s|%.*s|%s",
     185                 :            :                      nidfmt?nidfmt->len:0, nidfmt?nidfmt->s:"",
     186                 :            :                      idpent?idpent->len:0, idpent?idpent->s:"",
     187                 :            :                      spqual?spqual->len:0, spqual?spqual->s:"",
     188                 :            :                      idpnid->len, idpnid->s,
     189                 :            :                      STRNULLCHK(mniptr));
     190                 :         43 :   ZX_FREE(cf->ctx, buf);
     191   [ +  +  -  + ]:         43 :   D("PUT USER idpnid(%.*s)", idpnid->len, idpnid->s);
     192                 :         43 :   return 1;
     193                 :            : }
     194                 :            : 
     195                 :            : static char* login_failed = "Login failed. Check username and password. Make sure you have an active local account. Or just try some other authentication method or another IdP.<p>";
     196                 :            : 
     197                 :            : /*() Locally authenticate user. If successful, create a session.
     198                 :            :  * Expects to get username and password in cgi->au and cgi->ap
     199                 :            :  * respectively. User authetication is done against local database or
     200                 :            :  * by default using /var/zxid/uid/uid/.pw file. When filesystem
     201                 :            :  * backend is used, for safety reasons the uid (user) component can
     202                 :            :  * not have certain characters, such as slash (/) or sequences like "..".
     203                 :            :  * See also: zxpasswd.c
     204                 :            :  *
     205                 :            :  * return:: 0 on failure and sets cgi->err; 1 on success  */
     206                 :            : 
     207                 :            : /* Called by:  zxid_idp_as_do, zxid_simple_idp_pw_authn, zxid_simple_idp_show_an */
     208                 :            : int zxid_pw_authn(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses)
     209                 :         20 : {
     210                 :         20 :   const char* meth = "??";
     211                 :            :   struct zx_str* ss;
     212                 :            :   unsigned char buf[ZXID_MAX_BUF];
     213                 :            :   unsigned char pw_buf[256];
     214                 :            :   unsigned char pw_hash[120];
     215                 :            :   yubikey_token_st yktok;
     216                 :            :   int len;
     217                 :            : 
     218   [ +  -  -  + ]:         20 :   if (!cgi->uid || !cgi->uid[0]) {
     219                 :          0 :     ERR("No uid (user's login name) supplied. %d", 0);
     220                 :          0 :     cgi->err = login_failed;
     221   [ #  #  #  #  :          0 :     D("no user name pw(%s)", STRNULLCHK(cgi->pw));
                   #  # ]
     222                 :          0 :     return 0;
     223                 :            :   }
     224                 :            : 
     225                 :            :   /* Check for filesystem unsafe characters. (*** Is this list complete?) */
     226   [ +  -  +  -  :         20 :   if (strstr(cgi->uid, "..") || strchr(cgi->uid, '/')
             +  -  -  + ]
     227                 :            :       || strchr(cgi->uid, '\\') || strchr(cgi->uid, '~')) {
     228                 :          0 :     ERR("uid(%s) is not filesystem safe", cgi->uid);
     229   [ #  #  #  #  :          0 :     D("pw(%s)", STRNULLCHK(cgi->pw));
                   #  # ]
     230                 :          0 :     cgi->err = login_failed;
     231                 :          0 :     return 0;
     232                 :            :   }
     233                 :            : 
     234                 :         20 :   len = strlen(cgi->uid);
     235         [ -  + ]:         20 :   if (len > 32) {  /* Yubikey */
     236                 :          0 :     meth = "yk";
     237                 :          0 :     strcpy((char*)pw_hash, cgi->uid + len - 32);
     238                 :          0 :     cgi->uid[len - 32] = 0;
     239   [ #  #  #  # ]:          0 :     D("yubikey user(%s) ticket(%s)", cgi->uid, pw_hash);
     240                 :            : 
     241                 :          0 :     snprintf((char*)buf, sizeof(buf)-1, "%suid/%s", cf->path, cgi->uid);
     242                 :          0 :     buf[sizeof(buf)-1] = 0;
     243                 :          0 :     len = read_all(sizeof(pw_buf), (char*)pw_buf, "ykspent", 1, "%s/.ykspent/%s", buf, pw_hash);
     244         [ #  # ]:          0 :     if (len) {
     245                 :          0 :       ERR("The One Time Password has already been spent. ticket(%s%s) buf(%.*s)", cgi->uid, pw_hash, len, pw_buf);
     246                 :          0 :       cgi->err = login_failed;
     247                 :          0 :       return 0;
     248                 :            :     }
     249         [ #  # ]:          0 :     if (!write_all_path_fmt("ykspent", sizeof(pw_buf), (char*)pw_buf, "%s/.ykspent/%s", (char*)buf, (char*)pw_hash, "1"))
     250                 :          0 :       return 0;
     251                 :            :     
     252                 :          0 :     len = read_all(sizeof(pw_buf), (char*)pw_buf, "ykaes", 1, "%s/.yk", buf);
     253   [ #  #  #  # ]:          0 :     D("buf    (%s) got=%d", pw_buf, len);
     254         [ #  # ]:          0 :     if (len < 32) {
     255                 :          0 :       ERR("User's %s/.yk file must contain aes128 key as 32 hexadecimal characters. Too few characters %d ticket(%s)", cgi->uid, len, pw_hash);
     256                 :          0 :       cgi->err = login_failed;
     257                 :          0 :       return 0;
     258                 :            :     }
     259         [ #  # ]:          0 :     if (len > 32) {
     260                 :          0 :       INFO("User's %s/.yk file must contain aes128 key as 32 hexadecimal characters. Too many characters %d ticket(%s). Truncating.", cgi->uid, len, pw_hash);
     261                 :          0 :       len = 32;
     262                 :          0 :       pw_buf[len] = 0;
     263                 :            :     }
     264                 :          0 :     zx_hexdec((char*)pw_buf, (char*)pw_buf, len, hex_trans);
     265                 :          0 :     ZERO (&yktok, sizeof(yktok));
     266                 :          0 :     zx_hexdec((void*)&yktok, (char*)pw_hash, 32, ykmodhex_trans);
     267                 :          0 :     yubikey_aes_decrypt((void*)&yktok, pw_buf);
     268   [ #  #  #  # ]:          0 :     D("internal uid %02x %02x %02x %02x %02x %02x counter=%d 0x%x timestamp=%d (hi=%x lo=%x) use=%d 0x%x rnd=0x%x crc=0x%x", yktok.uid[0], yktok.uid[1], yktok.uid[2], yktok.uid[3], yktok.uid[4], yktok.uid[5], yktok.ctr, yktok.ctr, (yktok.tstph << 16) | yktok.tstpl, yktok.tstph, yktok.tstpl, yktok.use, yktok.use, yktok.rnd, yktok.crc);
     269                 :            :     
     270         [ #  # ]:          0 :     if (!yubikey_crc_ok_p((unsigned char*)&yktok)) {
     271   [ #  #  #  # ]:          0 :       D("yubikey ticket validation failure %d", 0);
     272                 :          0 :       cgi->err = login_failed;
     273                 :          0 :       return 0;
     274                 :            :     }
     275                 :            :   } else {
     276   [ +  -  -  + ]:         20 :     if (!cgi->pw || !cgi->pw[0]) {
     277                 :          0 :       ERR("No password supplied. uid(%s)", cgi->uid);
     278                 :          0 :       cgi->err = login_failed;
     279                 :          0 :       return 0;
     280                 :            :     }
     281                 :            :   
     282                 :            :     /* *** Add here support for other authentication backends */
     283                 :            : 
     284                 :         20 :     meth = "pw";
     285                 :            : 
     286                 :         20 :     len = read_all(sizeof(pw_buf), (char*)pw_buf, "pw_authn", 1,
     287                 :            :                    "%s" ZXID_UID_DIR "%s/.pw", cf->path, cgi->uid);
     288         [ -  + ]:         20 :     if (len < 1) {
     289                 :          0 :       ERR("No account found for uid(%s) or account does not have .pw file.", cgi->uid);
     290   [ #  #  #  # ]:          0 :       D("pw(%s)", cgi->pw);
     291                 :          0 :       cgi->err = login_failed;
     292                 :          0 :       return 0;
     293                 :            :     }
     294                 :            :     
     295         [ +  - ]:         20 :     if (len) {
     296         [ -  + ]:         20 :       if (pw_buf[len-1] == '\012') --len;
     297         [ -  + ]:         20 :       if (pw_buf[len-1] == '\015') --len;
     298                 :            :     }
     299                 :         20 :     pw_buf[len] = 0;
     300   [ +  -  -  + ]:         20 :     D("pw_buf (%s) len=%d", pw_buf, len);
     301                 :            : 
     302         [ +  + ]:         20 :     if (!memcmp(pw_buf, "$1$", sizeof("$1$")-1)) {
     303                 :          9 :       zx_md5_crypt(cgi->pw, (char*)pw_buf, (char*)pw_hash);
     304   [ +  -  -  + ]:          9 :       D("pw_hash(%s)", pw_hash);
     305         [ -  + ]:          9 :       if (strcmp((char*)pw_buf, (char*)pw_hash)) {
     306                 :          0 :         ERR("Bad password. uid(%s)", cgi->uid);
     307   [ #  #  #  # ]:          0 :         D("md5 pw(%s) .pw(%s) pw_hash(%s)", cgi->pw, pw_buf, pw_hash);
     308                 :          0 :         cgi->err = login_failed;
     309                 :          0 :         return 0;
     310                 :            :       }
     311                 :            : #ifdef USE_OPENSSL
     312         [ -  + ]:         11 :     } else if (!memcmp(pw_buf, "$c$", sizeof("$c$")-1)) {
     313                 :          0 :       DES_fcrypt(cgi->pw, (char*)pw_buf+3, (char*)pw_hash);
     314   [ #  #  #  # ]:          0 :       D("pw_hash(%s)", pw_hash);
     315         [ #  # ]:          0 :       if (strcmp((char*)buf+3, (char*)pw_hash)) {
     316                 :          0 :         ERR("Bad password for uid(%s)", cgi->uid);
     317   [ #  #  #  # ]:          0 :         D("crypt pw(%s) .pw(%s) pw_hash(%s)", cgi->pw, pw_buf, pw_hash);
     318                 :          0 :         cgi->err = login_failed;
     319                 :          0 :         return 0;
     320                 :            :       }
     321                 :            : #endif
     322   [ +  -  -  + ]:         11 :     } else if (ONE_OF_2(pw_buf[0], '$', '_')) {
     323                 :          0 :       ERR("Unsupported password hash. uid(%s)", cgi->uid);
     324   [ #  #  #  # ]:          0 :       D("pw(%s) .pw(%s)", cgi->pw, pw_buf);
     325                 :          0 :       cgi->err = login_failed;
     326                 :          0 :       return 0;
     327                 :            :     } else {
     328         [ +  + ]:         11 :       if (strcmp((char*)pw_buf, cgi->pw)) {
     329                 :          2 :         ERR("Bad password. uid(%s)", cgi->uid);
     330   [ +  -  -  + ]:          2 :         D("pw(%s) .pw(%s)", cgi->pw, pw_buf);
     331                 :          2 :         cgi->err = login_failed;
     332                 :          2 :         return 0;
     333                 :            :       }
     334                 :            :     }
     335                 :            :   }
     336                 :            : 
     337                 :            :   /* Successful login. Establish session. */
     338                 :            : 
     339                 :         18 :   ZERO(ses, sizeof(zxid_ses));
     340                 :         18 :   ses->magic = ZXID_SES_MAGIC;
     341                 :         18 :   ses->an_instant = time(0);  /* This will be later used by AuthnStatement constructor. */
     342                 :         18 :   ses->an_ctx = cf->issue_authnctx_pw;  /* *** Should also depend on how user was registered */
     343                 :            :   /* Master session. Each pairwise SSO has its own to avoid correlation, see zxid_mk_an_stmt() */
     344                 :         18 :   ss = zxid_mk_id(cf, "MMSES", ZXID_ID_BITS);
     345                 :         18 :   ses->sesix = ss->s;
     346                 :         18 :   ZX_FREE(cf->ctx, ss);
     347                 :         18 :   ses->sid = cgi->sid = ses->sesix;
     348                 :         18 :   ses->uid = cgi->uid;
     349                 :         18 :   zxid_put_ses(cf, ses);
     350   [ +  -  +  - ]:         18 :   if (cf->ses_cookie_name && *cf->ses_cookie_name) {
     351   [ +  -  -  + ]:         18 :     ses->setcookie = zx_alloc_sprintf(cf->ctx, 0, "%s=%s; path=/%s",
     352                 :            :                                       cf->ses_cookie_name, ses->sid,
     353                 :            :                                       ONE_OF_2(cf->url[4], 's', 'S')?"; secure":"");
     354                 :         18 :     ses->cookie = zx_alloc_sprintf(cf->ctx, 0, "$Version=1; %s=%s",
     355                 :            :                                    cf->ses_cookie_name, ses->sid);
     356                 :            :   }
     357                 :         18 :   INFO("LOCAL LOGIN SUCCESSFUL. sid(%s) uid(%s) %s", cgi->sid, cgi->uid, meth);
     358                 :         18 :   zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "K", "INEWSES", ses->sid, "uid(%s) %s", ses->uid, meth);
     359         [ +  - ]:         18 :   if (cf->loguser)
     360                 :         18 :     zxlogusr(cf, ses->uid, 0, 0, 0, 0, 0, 0, 0, "N", "K", "INEWSES", ses->sid, "uid(%s) %s", ses->uid, meth);
     361                 :         18 :   return 1;
     362                 :            : }
     363                 :            : 
     364                 :            : /* EOF  --  zxiduser.c */

Generated by: LCOV version 1.9