LCOV - code coverage report
Current view: top level - zxid - zxidps.c (source / functions) Hit Total Coverage
Test: ZXID Code Coverage Lines: 38 315 12.1 %
Date: 2010-12-19 Functions: 4 13 30.8 %
Branches: 7 222 3.2 %

           Branch data     Line data    Source code
       1                 :            : /* zxidps.c  -  People Service
       2                 :            :  * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
       3                 :            :  * Copyright (c) 2010 Risaris Ltd, 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: zxiddi.c,v 1.2 2009-11-24 23:53:40 sampo Exp $
      10                 :            :  *
      11                 :            :  * 16.9.2010, created --Sampo
      12                 :            :  *
      13                 :            :  * See also zxcall for client
      14                 :            :  * - liberty-idwsf-overview-v2.0.pdf sec 2.3 and 2.4 (pp.15-31) for use cases
      15                 :            :  * - liberty-idwsf-people-service-v1.0.pdf, sec 4.4 Elements Supporting Invitation (pp.53-57)
      16                 :            :  *
      17                 :            :  *  zxcot -e http://idp.tas3.pt:8081/zxididp?o=S 'People Svc' \
      18                 :            :  *    http://idp.tas3.pt:8081/zxididp?o=B urn:liberty:ps:2006-08 \
      19                 :            :  *  | zxcot -b /var/zxid/idpdimd
      20                 :            :  */
      21                 :            : 
      22                 :            : #include "platform.h"  /* for dirent.h */
      23                 :            : #include "errmac.h"
      24                 :            : #include "zxid.h"
      25                 :            : #include "zxidpriv.h"
      26                 :            : #include "zxidutil.h"
      27                 :            : #include "zxidconf.h"
      28                 :            : #include "saml2.h"
      29                 :            : #include "wsf.h"
      30                 :            : #include "c/zx-const.h"
      31                 :            : #include "c/zx-ns.h"
      32                 :            : #include "c/zx-data.h"
      33                 :            : 
      34                 :            : /* Called by:  zxid_psobj_dec, zxid_psobj_enc */
      35                 :            : static int zxid_psobj_key_setup(zxid_conf* cf, struct zx_str* eid, char* symkey)
      36                 :         74 : {
      37         [ +  + ]:         74 :   if (!cf->psobj_symkey[0])
      38                 :         24 :     zx_get_symkey(cf, "psobj-enc.key", cf->psobj_symkey);
      39                 :         74 :   zx_raw_digest2(cf->ctx, symkey, "SHA1", strlen(cf->psobj_symkey), cf->psobj_symkey, eid->len, eid->s);
      40                 :         74 :   return 20;
      41                 :            : }
      42                 :            : 
      43                 :            : /*() Encrypt and safe_base64 encode psobj identifier for an entity.
      44                 :            :  *
      45                 :            :  * ObjectID (psobj) has particlar privacy threat in that several WSCs may
      46                 :            :  * see them and be able to correlate about the user that the object refers
      47                 :            :  * to (see brief discussion in sec 2.1.4 "<ObjectID> Element", ll.278-281,
      48                 :            :  * of [PeopleSvc].
      49                 :            :  *
      50                 :            :  * We adopt solution where psobj issued towards an entity (SP, WSC) is
      51                 :            :  * the psobj encrypted (AES-128-CBC) with key consisting of concatenation
      52                 :            :  * of secret (/var/zxid/pem/psobj-enc.key) known to ps server (i.e. the
      53                 :            :  * zxididp) and the Entity ID of the entity. */
      54                 :            : 
      55                 :            : /* Called by:  zxid_mk_an_stmt, zxid_ps_addent_invite */
      56                 :            : struct zx_str* zxid_psobj_enc(zxid_conf* cf, struct zx_str* eid, const char* prefix, struct zx_str* psobj)
      57                 :         72 : {
      58                 :            :   char* lim;
      59                 :            :   char symkey[20];
      60                 :            :   struct zx_str key;
      61                 :            :   struct zx_str* ss;
      62                 :            :   struct zx_str* rr;
      63                 :         72 :   int prefix_len = strlen(prefix);
      64                 :         72 :   zxid_psobj_key_setup(cf, eid, symkey);
      65                 :         72 :   key.len = 16;
      66                 :         72 :   key.s = symkey;
      67                 :         72 :   ss = zx_raw_cipher(cf->ctx, "AES-128-CBC", 1, &key, psobj->len, psobj->s, 16, 0);
      68                 :         72 :   rr = zx_new_len_str(cf->ctx, prefix_len+SIMPLE_BASE64_LEN(ss->len)+1);
      69                 :         72 :   strcpy(rr->s, prefix);
      70                 :         72 :   lim = base64_fancy_raw(ss->s, ss->len, rr->s+prefix_len, safe_basis_64, 1<<31, 0, "", '=');
      71                 :         72 :   *lim = 0;
      72                 :         72 :   rr->len = lim - rr->s;
      73                 :         72 :   zx_str_free(cf->ctx, ss);
      74                 :         72 :   return rr;
      75                 :            : }
      76                 :            : 
      77                 :            : /*() Decrypt psobj identifier from an entity. */
      78                 :            : 
      79                 :            : /* Called by:  zxid_idp_slo_do, zxid_ps_addent_invite */
      80                 :            : struct zx_str* zxid_psobj_dec(zxid_conf* cf, struct zx_str* eid, const char* prefix, struct zx_str* psobj)
      81                 :          2 : {
      82                 :            :   char* lim;
      83                 :            :   char symkey[20];
      84                 :            :   struct zx_str key;
      85                 :            :   struct zx_str* ss;
      86                 :            :   struct zx_str* rr;
      87                 :          2 :   int prefix_len = strlen(prefix);
      88   [ +  -  +  -  :          2 :   if (!eid || !psobj || psobj->len < prefix_len) {
                   -  + ]
      89                 :          0 :     ERR("Null eid or psobj, or too short psobj %p", psobj);
      90                 :          0 :     return 0;
      91                 :            :   }
      92         [ -  + ]:          2 :   if (memcmp(prefix, psobj->s, prefix_len)) {
      93                 :          0 :     ERR("psobj(%.*s) does not match prefix(%s)", psobj->len, psobj->s, prefix);
      94                 :          0 :     return 0;
      95                 :            :   }
      96                 :          2 :   zxid_psobj_key_setup(cf, eid, symkey);
      97                 :          2 :   key.len = 16;
      98                 :          2 :   key.s = symkey;
      99                 :          2 :   rr = zx_new_len_str(cf->ctx, SIMPLE_BASE64_PESSIMISTIC_DECODE_LEN(psobj->len));
     100                 :          2 :   lim = unbase64_raw(psobj->s+prefix_len, psobj->s+psobj->len, rr->s, zx_std_index_64);
     101                 :          2 :   rr->len = lim - rr->s;
     102                 :          2 :   ss = zx_raw_cipher(cf->ctx, "AES-128-CBC", 0, &key, rr->len-16, rr->s+16, 16, rr->s);
     103                 :          2 :   zx_str_free(cf->ctx, rr);
     104                 :          2 :   return ss;
     105                 :            : }
     106                 :            : 
     107                 :            : /*() Render the linked list of delegated permissions to a string */
     108                 :            : 
     109                 :            : /* Called by:  zxid_put_invite, zxid_put_psobj */
     110                 :            : char* zxid_render_perms(zxid_conf* cf, struct zxid_perm* perms)
     111                 :          0 : {
     112                 :          0 :   int n, len = 0;
     113                 :            :   struct zxid_perm* perm;
     114                 :            :   char* ret;
     115                 :            :   char* p;
     116                 :            :   
     117                 :            :   /* Length computation phase */
     118                 :            :   
     119         [ #  # ]:          0 :   for (perm = perms; perm; perm = perm->n)
     120   [ #  #  #  # ]:          0 :     len += sizeof("perm: ")-1 + (perm->eid?perm->eid->len:0) + 1 + (perm->qs?perm->qs->len:0) + 1;
     121                 :            :   
     122                 :          0 :   ret = p = ZX_ALLOC(cf->ctx, len+1);
     123                 :            :   
     124                 :            :   /* Rendering phase */
     125                 :            :   
     126         [ #  # ]:          0 :   for (perm = perms; perm; perm = perm->n) {
     127   [ #  #  #  #  :          0 :     n = sprintf(p, "perm: %.*s$%.*s\n",
             #  #  #  # ]
     128                 :            :                 perm->eid?perm->eid->len:0, perm->eid?perm->eid->s:"",
     129                 :            :                 perm->qs?perm->qs->len:0,   perm->qs?perm->qs->s:"");
     130                 :          0 :     p += n;
     131                 :            :   }
     132                 :            :   
     133   [ #  #  #  # ]:          0 :   ASSERTOP(p-ret, ==, len);
     134                 :          0 :   *p = 0; /* nul terminate */
     135                 :          0 :   return ret;
     136                 :            : }
     137                 :            : 
     138                 :            : /*() Render the linked list of invitation IDs to a string */
     139                 :            : 
     140                 :            : /* Called by:  zxid_put_psobj x2 */
     141                 :            : char* zxid_render_str_list(zxid_conf* cf, struct zx_str* strs, const char* attr_name)
     142                 :          0 : {
     143                 :          0 :   int n, len = 0, atn_len = strlen(attr_name);
     144                 :            :   struct zx_str* str;
     145                 :            :   char* ret;
     146                 :            :   char* p;
     147                 :            :   
     148                 :            :   /* Length computation phase */
     149                 :            :   
     150         [ #  # ]:          0 :   for (str = strs; str; str = str->n)
     151                 :          0 :     len += atn_len + sizeof(": ")-1 + str->len + 1;
     152                 :            :   
     153                 :          0 :   ret = p = ZX_ALLOC(cf->ctx, len+1);
     154                 :            :   
     155                 :            :   /* Rendering phase */
     156                 :            :   
     157         [ #  # ]:          0 :   for (str = strs; str; str = str->n) {
     158                 :          0 :     n = sprintf(p, "%s: %.*s\n", attr_name, str->len, str->s);
     159                 :          0 :     p += n;
     160                 :            :   }
     161                 :            :   
     162   [ #  #  #  # ]:          0 :   ASSERTOP(p-ret, ==, len);
     163                 :          0 :   *p = 0; /* nul terminate */
     164                 :          0 :   return ret;
     165                 :            : }
     166                 :            : 
     167                 :            : /*() Create new invitation in file system. */
     168                 :            : 
     169                 :            : /* Called by:  zxid_ps_addent_invite */
     170                 :            : int zxid_put_invite(zxid_conf* cf, struct zxid_invite* inv)
     171                 :          0 : {
     172                 :            :   char buf[ZXID_MAX_USER];
     173                 :            :   char invid_c[ZXID_MAX_USER];
     174                 :          0 :   char* perms = zxid_render_perms(cf, inv->perms);
     175                 :          0 :   memcpy(invid_c, inv->invid->s, MIN(inv->invid->len, sizeof(invid_c)-1));
     176                 :          0 :   invid_c[sizeof(invid_c)-1] = 0;
     177                 :            : 
     178   [ #  #  #  #  :          0 :   write_all_path_fmt("put_inv", ZXID_MAX_USER, buf,
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     179                 :            :                      "%s" ZXID_INV_DIR "%s", cf->path, invid_c,
     180                 :            :                      "dn: invid=%.*s\ninvid: %.*s\nuid: %s\ndesc: %.*s\npsobj: %.*s\nps2spredir: %.*s\nmaxusage: %d\nusage: %d\nstarts: %s\nexpires: %s\n%s\n\n",
     181                 :            :                      inv->invid->len, inv->invid->s,
     182                 :            :                      inv->invid->len, inv->invid->s,
     183                 :            :                      inv->uid,
     184                 :            :                      inv->desc?inv->desc->len:0, inv->desc?inv->desc->s:"",
     185                 :            :                      inv->psobj?inv->psobj->len:0, inv->psobj?inv->psobj->s:"",
     186                 :            :                      inv->ps2spredir?inv->ps2spredir->len:0, inv->ps2spredir?inv->ps2spredir->s:"",
     187                 :            :                      inv->maxusage,
     188                 :            :                      inv->usage,
     189                 :            :                      zxid_date_time(cf, inv->starts),
     190                 :            :                      zxid_date_time(cf, inv->expires),
     191                 :            :                      STRNULLCHK(perms));
     192   [ #  #  #  # ]:          0 :   D("PUT INVITATION invid(%s)", invid_c);
     193                 :          0 :   return 1;
     194                 :            : }
     195                 :            : 
     196                 :            : /*() Create new People Service Object in file system. */
     197                 :            : 
     198                 :            : /* Called by:  zxid_ps_addent_invite */
     199                 :            : int zxid_put_psobj(zxid_conf* cf, struct zxid_psobj* obj)
     200                 :          0 : {
     201                 :          0 :   char* buf = ZX_ALLOC(cf->ctx, ZXID_MAX_USER);
     202                 :          0 :   char* children = 0;  /* *** groups and children not supported yet. */
     203                 :          0 :   char* tags = zxid_render_str_list(cf, obj->invids, "tag");
     204                 :          0 :   char* invids = zxid_render_str_list(cf, obj->invids, "invid");
     205                 :          0 :   char* perms = zxid_render_perms(cf, obj->perms);
     206                 :          0 :   obj->mod_secs = time(0);
     207                 :            :   
     208   [ #  #  #  #  :          0 :   write_all_path_fmt("put_psobj", ZXID_MAX_USER, buf,
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     209                 :            :                      "%s" ZXID_UID_DIR "%s", cf->path, obj->uid,
     210                 :            :                      "dn: psobj=%.*s,uid=%s\npsobj: %.*s\nowner: %s\nidpnid: %.*s\ndispname: %.*s\nnodetype: %d\ncreated: %s\nmodified: %s\n%s%s%s%s\n\n",
     211                 :            :                      obj->psobj->len, obj->psobj->s, obj->uid,
     212                 :            :                      obj->psobj->len, obj->psobj->s, obj->uid,
     213                 :            :                      obj->idpnid?obj->idpnid->len:0, obj->idpnid?obj->idpnid->s:"",
     214                 :            :                      obj->dispname?obj->dispname->len:0, obj->dispname?obj->dispname->s:"",  /* *** Should really support multiple */
     215                 :            :                      obj->nodetype,
     216                 :            :                      zxid_date_time(cf, obj->create_secs),
     217                 :            :                      zxid_date_time(cf, obj->mod_secs),
     218                 :            :                      STRNULLCHK(children),
     219                 :            :                      STRNULLCHK(tags),
     220                 :            :                      STRNULLCHK(invids),
     221                 :            :                      STRNULLCHK(perms));
     222                 :          0 :   ZX_FREE(cf->ctx, buf);
     223   [ #  #  #  # ]:          0 :   D("PUT PSOBJ(%.*s)", obj->psobj->len, obj->psobj->s);
     224                 :          0 :   return 1;
     225                 :            : }
     226                 :            : 
     227                 :            : /*() Populate psobj from LDIF. Parse LDIF format and insert attributes to struct.
     228                 :            :  * The input is temporarily modified and then restored. Do not pass const string. */
     229                 :            : 
     230                 :            : /* Called by: */
     231                 :            : int zxid_parse_psobj(zxid_conf* cf, struct zxid_psobj* obj, char* p, const char* lk)
     232                 :          0 : {
     233                 :            :   char* name;
     234                 :            :   char* val;
     235                 :            :   char* q;
     236                 :            :   struct zx_str* ss;
     237                 :            :   struct zxid_perm* perm;
     238                 :            : 
     239         [ #  # ]:          0 :   for (; p; ++p) {
     240                 :          0 :     name = p;
     241                 :          0 :     p = strstr(p, ": ");
     242         [ #  # ]:          0 :     if (!p)
     243                 :          0 :       break;
     244                 :          0 :     *p = 0;
     245                 :          0 :     val = p+2;
     246                 :          0 :     p = strchr(val, '\n');  /* *** parsing LDIF is fragile if values are multiline */
     247         [ #  # ]:          0 :     if (p)
     248                 :          0 :       *p = 0;
     249                 :            : 
     250   [ #  #  #  # ]:          0 :     D("%s: ATTR(%s)=VAL(%s)", lk, name, val);
     251                 :            : 
     252   [ #  #  #  #  :          0 :     switch (name[0]) {
                   #  # ]
     253                 :            :     case 'd':
     254         [ #  # ]:          0 :       if (!strcmp(name, "dn"))
     255                 :          0 :         goto next;
     256         [ #  # ]:          0 :       if (!strcmp(name, "dispname")) {
     257                 :          0 :         obj->dispname = zx_dup_str(cf->ctx, val);
     258                 :          0 :         goto next;
     259                 :            :       }
     260                 :          0 :       break;
     261                 :            :     case 'i':
     262         [ #  # ]:          0 :       if (!strcmp(name, "idpnid")) {
     263                 :          0 :         obj->idpnid = zx_dup_str(cf->ctx, val);
     264                 :          0 :         goto next;
     265                 :            :       }
     266         [ #  # ]:          0 :       if (!strcmp(name, "invid")) {
     267                 :          0 :         ss = zx_dup_str(cf->ctx, val);
     268                 :          0 :         ss->n = obj->invids;
     269                 :          0 :         obj->invids = ss;
     270                 :          0 :         goto next;
     271                 :            :       }
     272                 :          0 :       break;
     273                 :            :     case 'p':
     274         [ #  # ]:          0 :       if (!strcmp(name, "psobj")) {
     275                 :          0 :         obj->psobj = zx_dup_str(cf->ctx, val);
     276                 :          0 :         goto next;
     277                 :            :       }
     278         [ #  # ]:          0 :       if (!strcmp(name, "psobjref")) {
     279                 :          0 :         ERR("%s: *** Child objects not yet supported (%s: %s)", lk, name, val);
     280                 :            :         /*obj->child = zx_dup_str(cf->ctx, val); *** */
     281                 :          0 :         goto next;
     282                 :            :       }
     283         [ #  # ]:          0 :       if (!strcmp(name, "perm")) {
     284                 :          0 :         perm = ZX_ZALLOC(cf->ctx, struct zxid_perm);
     285                 :          0 :         q = strchr(val, '$');
     286         [ #  # ]:          0 :         if (q) {
     287                 :          0 :           perm->eid = zx_dup_len_str(cf->ctx, q-val, val);
     288                 :          0 :           perm->qs  = zx_dup_str(cf->ctx, q);
     289                 :            :         } else
     290                 :          0 :           perm->eid = zx_dup_str(cf->ctx, val);
     291                 :          0 :         perm->n = obj->perms;
     292                 :          0 :         obj->perms = perm;
     293                 :          0 :         goto next;
     294                 :            :       }
     295                 :          0 :       break;
     296                 :            :     case 't':
     297         [ #  # ]:          0 :       if (!strcmp(name, "tag")) {
     298                 :          0 :         ss = zx_dup_str(cf->ctx, val);
     299                 :          0 :         ss->n = obj->tags;
     300                 :          0 :         obj->tags = ss;
     301                 :          0 :         goto next;
     302                 :            :       }
     303                 :          0 :       break;
     304                 :            :     case 'u':
     305         [ #  # ]:          0 :       if (!strcmp(name, "uid")) {
     306                 :          0 :         obj->uid = zx_dup_cstr(cf->ctx, val);
     307                 :          0 :         goto next;
     308                 :            :       }
     309                 :            :       break;
     310                 :            :     }
     311                 :          0 :     ERR("%s: Unknown name(%s) val(%s) in psobj LDIF file. Ignored.", lk, name, val);
     312                 :            : 
     313                 :          0 :   next:
     314                 :          0 :     val[-2] = ':'; /* restore */
     315         [ #  # ]:          0 :     if (p)
     316                 :          0 :       *p = '\n';
     317                 :            :     else
     318                 :          0 :       break;
     319                 :            :   }
     320                 :          0 :   return 1;
     321                 :            : }
     322                 :            : 
     323                 :            : /*() Populate invitation from LDIF. Parse LDIF format and insert attributes to struct.
     324                 :            :  * The input is temporarily modified and then restored. Do not pass const string. */
     325                 :            : 
     326                 :            : /* Called by:  zxid_ps_accept_invite, zxid_ps_finalize_invite */
     327                 :            : int zxid_parse_invite(zxid_conf* cf, struct zxid_invite* inv, char* p, const char* lk)
     328                 :          0 : {
     329                 :            :   char* name;
     330                 :            :   char* val;
     331                 :            :   char* q;
     332                 :            :   struct zxid_perm* perm;
     333                 :            : 
     334         [ #  # ]:          0 :   for (; p; ++p) {
     335                 :          0 :     name = p;
     336                 :          0 :     p = strstr(p, ": ");
     337         [ #  # ]:          0 :     if (!p)
     338                 :          0 :       break;
     339                 :          0 :     *p = 0;
     340                 :          0 :     val = p+2;
     341                 :          0 :     p = strchr(val, '\n');  /* *** parsing LDIF is fragile if values are multiline */
     342         [ #  # ]:          0 :     if (p)
     343                 :          0 :       *p = 0;
     344                 :            : 
     345   [ #  #  #  # ]:          0 :     D("%s: ATTR(%s)=VAL(%s)", lk, name, val);
     346                 :            : 
     347   [ #  #  #  #  :          0 :     switch (name[0]) {
             #  #  #  # ]
     348                 :            :     case 'd':
     349         [ #  # ]:          0 :       if (!strcmp(name, "dn"))
     350                 :          0 :         goto next;
     351         [ #  # ]:          0 :       if (!strcmp(name, "desc")) {
     352                 :          0 :         inv->desc = zx_dup_str(cf->ctx, val);
     353                 :          0 :         goto next;
     354                 :            :       }
     355                 :          0 :       break;
     356                 :            :     case 'e':
     357         [ #  # ]:          0 :       if (!strcmp(name, "expires")) {
     358                 :          0 :         inv->expires = zx_date_time_to_secs(val);
     359                 :          0 :         goto next;
     360                 :            :       }
     361                 :          0 :       break;
     362                 :            :     case 'i':
     363         [ #  # ]:          0 :       if (!strcmp(name, "invid")) {
     364                 :          0 :         inv->invid = zx_dup_str(cf->ctx, val);
     365                 :          0 :         goto next;
     366                 :            :       }
     367                 :          0 :       break;
     368                 :            :     case 'm':
     369         [ #  # ]:          0 :       if (!strcmp(name, "maxusage")) {
     370                 :          0 :         sscanf(val, "%i", &inv->maxusage);
     371                 :          0 :         goto next;
     372                 :            :       }
     373                 :          0 :       break;
     374                 :            :     case 'p':
     375         [ #  # ]:          0 :       if (!strcmp(name, "psobj")) {
     376                 :          0 :         inv->psobj = zx_dup_str(cf->ctx, val);
     377                 :          0 :         goto next;
     378                 :            :       }
     379         [ #  # ]:          0 :       if (!strcmp(name, "ps2spredir")) {
     380                 :          0 :         inv->ps2spredir = zx_dup_str(cf->ctx, val);
     381                 :          0 :         goto next;
     382                 :            :       }
     383         [ #  # ]:          0 :       if (!strcmp(name, "perm")) {
     384                 :          0 :         perm = ZX_ZALLOC(cf->ctx, struct zxid_perm);
     385                 :          0 :         q = strchr(val, '$');
     386         [ #  # ]:          0 :         if (q) {
     387                 :          0 :           perm->eid = zx_dup_len_str(cf->ctx, q-val, val);
     388                 :          0 :           perm->qs  = zx_dup_str(cf->ctx, q);
     389                 :            :         } else
     390                 :          0 :           perm->eid = zx_dup_str(cf->ctx, val);
     391                 :          0 :         perm->n = inv->perms;
     392                 :          0 :         inv->perms = perm;
     393                 :          0 :         goto next;
     394                 :            :       }
     395                 :          0 :       break;
     396                 :            :     case 's':
     397         [ #  # ]:          0 :       if (!strcmp(name, "starts")) {
     398                 :          0 :         inv->starts = zx_date_time_to_secs(val);
     399                 :          0 :         goto next;
     400                 :            :       }
     401                 :          0 :       break;
     402                 :            :     case 'u':
     403         [ #  # ]:          0 :       if (!strcmp(name, "uid")) {
     404                 :          0 :         inv->uid = zx_dup_cstr(cf->ctx, val);
     405                 :          0 :         goto next;
     406                 :            :       }
     407         [ #  # ]:          0 :       if (!strcmp(name, "usage")) {
     408                 :          0 :         sscanf(val, "%i", &inv->usage);
     409                 :          0 :         goto next;
     410                 :            :       }
     411                 :            :       break;
     412                 :            :     }
     413                 :          0 :     ERR("%s: Unknown name(%s) val(%s) in invite LDIF file. Ignored.", lk, name, val);
     414                 :            : 
     415                 :          0 :   next:
     416                 :          0 :     val[-2] = ':'; /* restore */
     417         [ #  # ]:          0 :     if (p)
     418                 :          0 :       *p = '\n';
     419                 :            :     else
     420                 :          0 :       break;
     421                 :            :   }
     422                 :          0 :   return 1;
     423                 :            : }
     424                 :            : 
     425                 :            : /*() Accept an invitation. Process a URL of form https://idp.tas3.pt/zxididp?o=D&inv=i123431
     426                 :            :  * Both logged in and not yet logged in cases are possible. */
     427                 :            : 
     428                 :            : /* Called by:  zxid_simple_no_ses_cf, zxid_simple_ses_active_cf */
     429                 :            : char* zxid_ps_accept_invite(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, int* res_len, int auto_flags)
     430                 :          1 : {
     431                 :          1 :   int now = time(0);
     432                 :            :   struct zxid_invite inv;
     433                 :            :   struct zx_str* ss;
     434                 :            :   char buf[ZXID_MAX_BUF];
     435                 :          1 :   int got = read_all(sizeof(buf), buf, "accept_invite", 1, "%s" ZXID_INV_DIR "%s",cf->path,cgi->inv);
     436         [ +  - ]:          1 :   if (!got) {
     437                 :          1 :     ERR("Invitation not found(%s)", cgi->inv);
     438                 :          1 :     cgi->err = "Invitation not found.";
     439                 :          1 :     return zxid_simple_show_err(cf, cgi, res_len, auto_flags);
     440                 :            :   }
     441                 :          0 :   zxid_parse_invite(cf, &inv, buf, "accept_invite");
     442         [ #  # ]:          0 :   if (inv.maxusage <= inv.usage) {
     443                 :          0 :     ERR("Invitation(%s) has already been used (max_usage=%d, usage=%d)", cgi->inv, inv.maxusage, inv.usage);
     444                 :          0 :     cgi->err = "Invitation has already been used.";
     445                 :          0 :     return zxid_simple_show_err(cf, cgi, res_len, auto_flags);
     446                 :            :   }
     447         [ #  # ]:          0 :   if (inv.starts > now) {
     448                 :          0 :     ERR("Invitation(%s) is not active yet (starts=%d, now=%d)", cgi->inv, inv.starts, now);
     449                 :          0 :     cgi->err = "Invitation is not active yet.";
     450                 :          0 :     return zxid_simple_show_err(cf, cgi, res_len, auto_flags);
     451                 :            :   }
     452         [ #  # ]:          0 :   if (inv.expires <= now) {
     453                 :          0 :     ERR("Invitation(%s) has expired (expire=%d, now=%d)", cgi->inv, inv.expires, now);
     454                 :          0 :     cgi->err = "Invitation has expired.";
     455                 :          0 :     return zxid_simple_show_err(cf, cgi, res_len, auto_flags);
     456                 :            :   }
     457                 :            :   
     458                 :          0 :   cgi->msg = "This screen aims to complete the invitation process you started by clicking on the invitation link. Once completed, you will be redirected to the web site where the delegated resource is available. To complete invitation, People Service needs to authenticate you with your Identity Provider (IdP). Please choose your Identity Provider from popup menu (or enter the IdP URL in the space provided) and click Login.";
     459                 :            :   
     460                 :          0 :   ss = zx_strf(cf->ctx, "o=G&inv=%s", cgi->inv);
     461                 :          0 :   cgi->rs = ss->s;
     462                 :          0 :   ZX_FREE(cf->ctx, ss);
     463                 :            : 
     464                 :          0 :   return zxid_simple_show_idp_sel(cf, cgi, res_len, auto_flags);
     465                 :            : }
     466                 :            : 
     467                 :            : /*() Finalize an invitation. This function is invoked after zxid_ps_accept_invite() (o=D)
     468                 :            :  * when user is returning from IdP, by way of o=G placed in RelayState. */
     469                 :            : 
     470                 :            : /* Called by:  zxid_simple_ses_active_cf */
     471                 :            : char* zxid_ps_finalize_invite(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, int* res_len, int auto_flags)
     472                 :          0 : {
     473                 :          0 :   int now = time(0);
     474                 :            :   struct zxid_invite inv;
     475                 :            :   struct zx_str* ss;
     476                 :            :   char buf[ZXID_MAX_BUF];
     477                 :          0 :   int got = read_all(sizeof(buf), buf, "finalize_invite", 1, "%s" ZXID_INV_DIR "%s",cf->path,cgi->inv);
     478         [ #  # ]:          0 :   if (!got) {
     479                 :          0 :     ERR("Invitation not found(%s)", cgi->inv);
     480                 :          0 :     cgi->err = "Invitation not found.";
     481                 :          0 :     return zxid_simple_show_err(cf, cgi, res_len, auto_flags);
     482                 :            :   }
     483                 :          0 :   zxid_parse_invite(cf, &inv, buf, "accept_invite");
     484         [ #  # ]:          0 :   if (inv.maxusage <= inv.usage) {
     485                 :          0 :     ERR("Invitation(%s) has already been used (max_usage=%d, usage=%d)", cgi->inv, inv.maxusage, inv.usage);
     486                 :          0 :     cgi->err = "Invitation has already been used.";
     487                 :          0 :     return zxid_simple_show_err(cf, cgi, res_len, auto_flags);
     488                 :            :   }
     489         [ #  # ]:          0 :   if (inv.starts > now) {
     490                 :          0 :     ERR("Invitation(%s) is not active yet (starts=%d, now=%d)", cgi->inv, inv.starts, now);
     491                 :          0 :     cgi->err = "Invitation is not active yet.";
     492                 :          0 :     return zxid_simple_show_err(cf, cgi, res_len, auto_flags);
     493                 :            :   }
     494         [ #  # ]:          0 :   if (inv.expires <= now) {
     495                 :          0 :     ERR("Invitation(%s) has expired (expire=%d, now=%d)", cgi->inv, inv.expires, now);
     496                 :          0 :     cgi->err = "Invitation has expired.";
     497                 :          0 :     return zxid_simple_show_err(cf, cgi, res_len, auto_flags);
     498                 :            :   }
     499                 :            :   
     500                 :          0 :   cgi->msg = "This screen aims to complete the invitation process you started by clicking on the invitation link. Once completed, you will be redirected to the web site where the delegated resource is available. To complete invitation, People Service needs to authenticate you with your Identity Provider (IdP). Please choose your Identity Provider from popup menu (or enter the IdP URL in the space provided) and click Login.";
     501                 :            :   
     502                 :          0 :   ss = zx_strf(cf->ctx, "o=G&inv=%s", cgi->inv);
     503                 :          0 :   cgi->rs = ss->s;
     504                 :          0 :   ZX_FREE(cf->ctx, ss);
     505                 :            : 
     506                 :          0 :   return zxid_simple_show_idp_sel(cf, cgi, res_len, auto_flags);
     507                 :            : }
     508                 :            : 
     509                 :            : /*() Add an entity to buddy store and obtain an invitation token.
     510                 :            :  * In fact this call just adds the invitation as we can not know
     511                 :            :  * who will respond to the invitation. The actual object will be
     512                 :            :  * created in zxid_ps_accept_invite(). If object repesenting the
     513                 :            :  * user already exists, that will be reused. Otherwise new
     514                 :            :  * object will be created.
     515                 :            :  * The permissions are expected to be passed in as special
     516                 :            :  * tag "perm". */
     517                 :            : 
     518                 :            : /* Called by:  zxid_sp_soap_dispatch */
     519                 :            : struct zx_ps_AddEntityResponse_s* zxid_ps_addent_invite(zxid_conf* cf, zxid_ses* ses, struct zx_ps_AddEntityRequest_s* req)
     520                 :          0 : {
     521                 :            :   struct zx_str* tag;
     522                 :          0 :   struct zx_ps_AddEntityResponse_s* resp = zx_NEW_ps_AddEntityResponse(cf->ctx,0);
     523                 :            :   struct zxid_invite* inv;
     524                 :            :   struct zxid_psobj* obj;
     525                 :            :   char uid[ZXID_MAX_USER];
     526                 :          0 :   D_INDENT("ps_inv: ");
     527                 :            : 
     528   [ #  #  #  # ]:          0 :   if (!req || !req->Object) {
     529                 :          0 :     ERR("Malformed request (%p): Object missing.", req);
     530                 :          0 :     resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "Fail", 0, 0, 0);
     531                 :          0 :     D_DEDENT("ps_inv: ");
     532                 :          0 :     return resp;
     533                 :            :   }
     534                 :            : 
     535         [ #  # ]:          0 :   if (!zxid_idp_map_nid2uid(cf, sizeof(uid), uid, ses->tgtnameid, &resp->Status)) {
     536                 :          0 :     D_DEDENT("ps_inv: ");
     537                 :          0 :     return resp;
     538                 :            :   }
     539                 :            :   
     540                 :          0 :   inv = ZX_ZALLOC(cf->ctx, struct zxid_invite);
     541                 :          0 :   inv->invid = zxid_mk_id(cf, "i", 48);  /* What is secure and sufficient space? */
     542                 :          0 :   inv->uid = uid;
     543                 :          0 :   inv->maxusage = 1;
     544                 :          0 :   inv->starts = time(0);
     545                 :          0 :   inv->expires = time(0) + 86400 * 30;  /* *** make configurable (about a month) */
     546   [ #  #  #  #  :          0 :   inv->ps2spredir = ZX_GET_CONTENT(req->PStoSPRedirectURL);
                   #  # ]
     547                 :          0 :   inv->perms = ZX_ZALLOC(cf->ctx, struct zxid_perm);
     548                 :          0 :   inv->perms->eid = ses->issuer;
     549                 :            : 
     550                 :          0 :   obj = ZX_ZALLOC(cf->ctx, struct zxid_psobj);
     551                 :            : #if 0
     552                 :            :   obj->psobj = req->Object->ObjectID ? zxid_psobj_dec(cf, ses->issuer, "ZO", req->Object->ObjectID) : zxid_mk_id(cf, "o", 48);  /* What is secure and sufficient space? */
     553                 :            : #else
     554         [ #  # ]:          0 :   if (req->Object->ObjectID) {
     555   [ #  #  #  #  :          0 :     ERR("AddEntityRequest contained ObjectID(%.*s), but AddEntity is about creating new objects and the object IDs are assigned by People Service, not client. Ignoring ObjectID.", ZX_GET_CONTENT_LEN(req->Object->ObjectID), ZX_GET_CONTENT_S(req->Object->ObjectID));
          #  #  #  #  #  
                #  #  # ]
     556                 :            :   }
     557                 :          0 :   obj->psobj = zxid_mk_id(cf, "o", 48);  /* What is secure and sufficient space? */
     558                 :            : #endif
     559                 :          0 :   obj->uid = uid;
     560   [ #  #  #  #  :          0 :   obj->dispname = ZX_GET_CONTENT(req->Object->DisplayName);
                   #  # ]
     561   [ #  #  #  #  :          0 :   obj->tags = ZX_GET_CONTENT(req->Object->Tag);
                   #  # ]
     562                 :          0 :   obj->invids = inv->invid;
     563                 :          0 :   obj->create_secs = time(0);
     564                 :            : 
     565                 :          0 :   inv->psobj = obj->psobj;
     566                 :          0 :   zxid_put_invite(cf, inv);
     567                 :          0 :   zxid_put_psobj(cf, obj);
     568                 :            : 
     569                 :            :   /* The invitation URL will be processed by zxid_ps_accept_invite(), see above. */
     570                 :          0 :   resp->SPtoPSRedirectURL
     571                 :            :     = zx_new_str_elem(cf->ctx, &resp->gg, zx_ps_SPtoPSRedirectURL_ELEM,
     572                 :            :                       zx_strf(cf->ctx, "%s?o=D&inv=%.*s", cf->url, inv->invid->len, inv->invid->s));
     573                 :          0 :   resp->Object = zx_NEW_ps_Object(cf->ctx, &resp->gg);
     574                 :          0 :   resp->Object->ObjectID = zx_new_str_elem(cf->ctx, &resp->Object->gg, zx_ps_ObjectID_ELEM, zxid_psobj_enc(cf, ses->issuer, "ZO", obj->psobj));
     575                 :          0 :   resp->Object->DisplayName = zx_NEW_ps_DisplayName(cf->ctx, &resp->Object->gg);
     576                 :          0 :   zx_add_content(cf->ctx, &resp->Object->DisplayName->gg, obj->dispname);
     577                 :          0 :   resp->Object->DisplayName->Locale = zx_ref_attr(cf->ctx, &resp->Object->DisplayName->gg, zx_Locale_ATTR, "xx");  /* unknown locale */
     578         [ #  # ]:          0 :   for (tag = obj->tags; tag; tag = tag->n) {
     579                 :          0 :     resp->Object->Tag = zx_NEW_ps_Tag(cf->ctx, &resp->Object->gg);
     580                 :          0 :     zx_add_content(cf->ctx, &resp->Object->Tag->gg, tag);
     581                 :            :   }
     582         [ #  # ]:          0 :   resp->Object->NodeType = zx_ref_attr(cf->ctx, &resp->Object->gg, zx_NodeType_ATTR, obj->nodetype?PS_COL:PS_ENT);
     583                 :          0 :   resp->Object->CreatedDateTime = zxid_date_time_attr(cf, &resp->Object->gg, zx_CreatedDateTime_ATTR, obj->create_secs);
     584                 :          0 :   resp->Object->ModifiedDateTime = zxid_date_time_attr(cf, &resp->Object->gg, zx_TimeStamp_ATTR, obj->mod_secs);
     585                 :          0 :   resp->TimeStamp = resp->Object->CreatedDateTime;
     586                 :          0 :   resp->id = zx_ref_len_attr(cf->ctx, &resp->gg, zx_id_ATTR, inv->invid->len, inv->invid->s);  /* *** why is ID requred by schema at all? */
     587                 :          0 :   resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "OK", 0, 0, 0);
     588                 :          0 :   zxlogwsp(cf, ses, "K", "PSINV", 0, "inv=%.*s", inv->invid->len, inv->invid->s);
     589                 :          0 :   D_DEDENT("ps_inv: ");
     590                 :          0 :   return resp;
     591                 :            : }
     592                 :            : 
     593                 :            : /*() Resolve an invitation token to identity */
     594                 :            : 
     595                 :            : /* Called by:  zxid_sp_soap_dispatch */
     596                 :            : struct zx_ps_ResolveIdentifierResponse_s* zxid_ps_resolv_id(zxid_conf* cf, zxid_ses* ses, struct zx_ps_ResolveIdentifierRequest_s* req)
     597                 :          0 : {
     598                 :          0 :   struct zx_ps_ResolveIdentifierResponse_s* resp = zx_NEW_ps_ResolveIdentifierResponse(cf->ctx,0);
     599                 :            :   struct zx_ps_ResolveInput_s* inp;
     600                 :            :   //struct zx_ps_ResolveOutput_s* out;
     601                 :          0 :   int n_resolv = 0;
     602                 :            :   char uid[ZXID_MAX_USER];
     603                 :          0 :   D_INDENT("ps_resolv: ");
     604                 :            :   
     605                 :            :   //resp->ID = zxid_mk_id(cf, "DIR", ZXID_ID_BITS);
     606                 :            :   
     607         [ #  # ]:          0 :   if (!zxid_idp_map_nid2uid(cf, sizeof(uid), uid, ses->tgtnameid, &resp->Status)) {
     608                 :          0 :     D_DEDENT("ps_resolv: ");
     609                 :          0 :     return resp;
     610                 :            :   }
     611                 :            : 
     612                 :          0 :   for (inp = req->ResolveInput;
     613   [ #  #  #  # ]:          0 :        inp && inp->gg.g.tok == zx_ps_ResolveInput_ELEM;
     614                 :          0 :        inp = (struct zx_ps_ResolveInput_s*)inp->gg.g.n) {
     615                 :            :     // ***
     616                 :            :   }
     617                 :            : 
     618                 :          0 :   resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "OK", 0, 0, 0);
     619                 :          0 :   zxlogwsp(cf, ses, "K", "PSRESOLVOK", 0, "n=%d", n_resolv);
     620                 :          0 :   D_DEDENT("ps_resolv: ");
     621                 :          0 :   return resp;
     622                 :            : }
     623                 :            : 
     624                 :            : /* EOF  --  zxidps.c */

Generated by: LCOV version 1.9