LCOV - code coverage report
Current view: top level - shishi/lib - principal.c (source / functions) Hit Total Coverage
Test: GNU Shishi Lines: 99 166 59.6 %
Date: 2010-05-20 Functions: 7 10 70.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 42 102 41.2 %

           Branch data     Line data    Source code
       1                 :            : /* principal.c --- Get and set default principal.
       2                 :            :  * Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008, 2010  Simon Josefsson
       3                 :            :  *
       4                 :            :  * This file is part of Shishi.
       5                 :            :  *
       6                 :            :  * Shishi is free software; you can redistribute it and/or modify it
       7                 :            :  * under the terms of the GNU General Public License as published by
       8                 :            :  * the Free Software Foundation; either version 3 of the License, or
       9                 :            :  * (at your option) any later version.
      10                 :            :  *
      11                 :            :  * Shishi is distributed in the hope that it will be useful, but
      12                 :            :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  * GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with Shishi; if not, see http://www.gnu.org/licenses or write
      18                 :            :  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
      19                 :            :  * Floor, Boston, MA 02110-1301, USA
      20                 :            :  *
      21                 :            :  */
      22                 :            : 
      23                 :            : #include "internal.h"
      24                 :            : 
      25                 :            : /**
      26                 :            :  * shishi_principal_default_guess:
      27                 :            :  *
      28                 :            :  * Guesses the principal name for the user, looking at environment
      29                 :            :  * variables SHISHI_USER and USER, or if that fails, returns the
      30                 :            :  * string "user".
      31                 :            :  *
      32                 :            :  * Return value: Returns guessed default principal for user as a
      33                 :            :  * string that has to be deallocated with free() by the caller.
      34                 :            :  **/
      35                 :            : char *
      36                 :          1 : shishi_principal_default_guess (void)
      37                 :            : {
      38                 :            :   const char *envuser;
      39                 :            : 
      40                 :          1 :   envuser = getenv ("SHISHI_USER");
      41         [ +  - ]:          1 :   if (!envuser)
      42                 :          1 :     envuser = getenv ("USER");
      43         [ -  + ]:          1 :   if (!envuser)
      44                 :          0 :     envuser = "user";
      45                 :            : 
      46                 :          1 :   return xstrdup (envuser);
      47                 :            : }
      48                 :            : 
      49                 :            : 
      50                 :            : /**
      51                 :            :  * shishi_principal_default:
      52                 :            :  * @handle: Shishi library handle create by shishi_init().
      53                 :            :  *
      54                 :            :  * The default principal name is the name in the environment variable
      55                 :            :  * USER, but can be overridden by specifying the environment variable
      56                 :            :  * SHISHI_USER.
      57                 :            :  *
      58                 :            :  * Return value: Returns the default principal name used in the
      59                 :            :  * library.  (Not a copy of it, so don't modify or deallocate it.)
      60                 :            :  **/
      61                 :            : const char *
      62                 :          1 : shishi_principal_default (Shishi * handle)
      63                 :            : {
      64         [ +  - ]:          1 :   if (!handle->default_principal)
      65                 :            :     {
      66                 :            :       char *p;
      67                 :          1 :       p = shishi_principal_default_guess ();
      68                 :          1 :       shishi_principal_default_set (handle, p);
      69                 :          1 :       free (p);
      70                 :            :     }
      71                 :            : 
      72                 :          1 :   return handle->default_principal;
      73                 :            : }
      74                 :            : 
      75                 :            : /**
      76                 :            :  * shishi_principal_default_set:
      77                 :            :  * @handle: Shishi library handle create by shishi_init().
      78                 :            :  * @principal: string with new default principal name, or NULL to
      79                 :            :  * reset to default.
      80                 :            :  *
      81                 :            :  * Set the default realm used in the library.  The string is copied
      82                 :            :  * into the library, so you can dispose of the variable immediately
      83                 :            :  * after calling this function.
      84                 :            :  **/
      85                 :            : void
      86                 :         15 : shishi_principal_default_set (Shishi * handle, const char *principal)
      87                 :            : {
      88                 :         15 :   free (handle->default_principal);
      89         [ +  + ]:         15 :   if (principal)
      90                 :          1 :     handle->default_principal = xstrdup (principal);
      91                 :            :   else
      92                 :         14 :     handle->default_principal = NULL;
      93                 :         15 : }
      94                 :            : 
      95                 :            : /**
      96                 :            :  * shishi_parse_name:
      97                 :            :  * @handle: Shishi library handle create by shishi_init().
      98                 :            :  * @name: Input principal name string, e.g. imap/mail.gnu.org@GNU.ORG.
      99                 :            :  * @principal: newly allocated output string with principal name.
     100                 :            :  * @realm: newly allocated output string with realm name.
     101                 :            :  *
     102                 :            :  * Split up principal name (e.g., "simon@JOSEFSSON.ORG") into two
     103                 :            :  * newly allocated strings, the principal ("simon") and realm
     104                 :            :  * ("JOSEFSSON.ORG").  If there is no realm part in NAME, REALM is set
     105                 :            :  * to NULL.
     106                 :            :  *
     107                 :            :  * Return value: Returns SHISHI_INVALID_PRINCIPAL_NAME if NAME is NULL
     108                 :            :  *   or ends with the escape character "\", or SHISHI_OK iff
     109                 :            :  *   successful
     110                 :            :  **/
     111                 :            : int
     112                 :          0 : shishi_parse_name (Shishi * handle, const char *name,
     113                 :            :                    char **principal, char **realm)
     114                 :            : {
     115                 :          0 :   const char *p = name;
     116                 :            :   const char *q;
     117                 :          0 :   int escaped = 0;
     118                 :            : 
     119         [ #  # ]:          0 :   if (!name)
     120                 :          0 :     return SHISHI_INVALID_PRINCIPAL_NAME;
     121                 :            : 
     122 [ #  # ][ #  # ]:          0 :   while (*p && (*p != '@' || escaped))
                 [ #  # ]
     123         [ #  # ]:          0 :     if (escaped)
     124                 :          0 :       escaped = 0;
     125         [ #  # ]:          0 :     else if (*p++ == '\\')
     126                 :          0 :       escaped = 1;
     127                 :            : 
     128         [ #  # ]:          0 :   if (escaped)
     129                 :          0 :     return SHISHI_INVALID_PRINCIPAL_NAME;
     130                 :            : 
     131         [ #  # ]:          0 :   if (principal)
     132                 :            :     {
     133                 :          0 :       *principal = xstrndup (name, p - name + 1);
     134                 :          0 :       (*principal)[p - name] = '\0';
     135                 :            :     }
     136                 :            : 
     137         [ #  # ]:          0 :   if (*p)
     138                 :            :     {
     139                 :          0 :       q = ++p;
     140                 :            : 
     141         [ #  # ]:          0 :       while (*q)
     142         [ #  # ]:          0 :         if (escaped)
     143                 :          0 :           escaped = 0;
     144         [ #  # ]:          0 :         else if (*q++ == '\\')
     145                 :          0 :           escaped = 1;
     146                 :            : 
     147         [ #  # ]:          0 :       if (escaped)
     148                 :          0 :         return SHISHI_INVALID_PRINCIPAL_NAME;
     149                 :            : 
     150         [ #  # ]:          0 :       if (realm)
     151                 :          0 :         *realm = xstrdup (p);
     152                 :            :     }
     153         [ #  # ]:          0 :   else if (realm)
     154                 :          0 :     *realm = NULL;
     155                 :            : 
     156                 :          0 :   return SHISHI_OK;
     157                 :            : }
     158                 :            : 
     159                 :            : /**
     160                 :            :  * shishi_principal_name:
     161                 :            :  * @handle: Shishi library handle create by shishi_init().
     162                 :            :  * @namenode: ASN.1 structure with principal in @namefield.
     163                 :            :  * @namefield: name of field in @namenode containing principal name.
     164                 :            :  * @out: pointer to newly allocated zero terminated string containing
     165                 :            :  *   principal name.  May be %NULL (to only populate @outlen).
     166                 :            :  * @outlen: pointer to length of @out on output, excluding terminating
     167                 :            :  *   zero.  May be %NULL (to only populate @out).
     168                 :            :  *
     169                 :            :  * Represent principal name in ASN.1 structure as zero-terminated
     170                 :            :  * string.  The string is allocate by this function, and it is the
     171                 :            :  * responsibility of the caller to deallocate it.  Note that the
     172                 :            :  * output length @outlen does not include the terminating zero.
     173                 :            :  *
     174                 :            :  * Return value: Returns SHISHI_OK iff successful.
     175                 :            :  **/
     176                 :            : int
     177                 :         16 : shishi_principal_name (Shishi * handle,
     178                 :            :                        Shishi_asn1 namenode,
     179                 :            :                        const char *namefield, char **out, size_t * outlen)
     180                 :            : {
     181                 :            :   char *format;
     182                 :            :   size_t i, j, n;
     183                 :         16 :   char *name = NULL;
     184                 :         16 :   size_t namelen = 0;
     185                 :            :   int res;
     186                 :            : 
     187                 :         16 :   asprintf (&format, "%s.name-string", namefield);
     188                 :         16 :   res = shishi_asn1_number_of_elements (handle, namenode, format, &n);
     189                 :         16 :   free (format);
     190         [ -  + ]:         16 :   if (res != SHISHI_OK)
     191                 :          0 :     return res;
     192                 :            : 
     193         [ +  + ]:         42 :   for (i = 1; i <= n; i++)
     194                 :            :     {
     195                 :            :       char *tmp;
     196                 :            :       size_t tmplen;
     197                 :            :       size_t safetmplen;
     198                 :            : 
     199                 :         26 :       asprintf (&format, "%s.name-string.?%d", namefield, i);
     200                 :         26 :       res = shishi_asn1_read (handle, namenode, format, &tmp, &tmplen);
     201                 :         26 :       free (format);
     202         [ -  + ]:         26 :       if (res != SHISHI_OK)
     203                 :          0 :         return res;
     204                 :            : 
     205                 :         26 :       safetmplen = tmplen;
     206         [ +  + ]:        208 :       for (j = 0; j < tmplen; j++)
     207 [ +  - ][ +  - ]:        182 :         if (tmp[j] == '@' || tmp[j] == '/' || tmp[j] == '\\')
                 [ -  + ]
     208                 :          0 :           safetmplen++;
     209         [ +  + ]:         26 :       if (i < n)
     210                 :         10 :         safetmplen++;
     211                 :            : 
     212                 :         26 :       name = xrealloc (name, namelen + safetmplen);
     213                 :            : 
     214         [ +  + ]:        208 :       for (j = 0; j < tmplen; j++)
     215                 :            :         {
     216 [ +  - ][ +  - ]:        182 :           if (tmp[j] == '@' || tmp[j] == '/' || tmp[j] == '\\')
                 [ -  + ]
     217                 :          0 :             name[namelen++] = '\\';
     218                 :        182 :           name[namelen++] = tmp[j];
     219                 :            :         }
     220                 :            : 
     221         [ +  + ]:         26 :       if (i < n)
     222                 :         10 :         name[namelen++] = '/';
     223                 :            : 
     224                 :         26 :       free (tmp);
     225                 :            :     }
     226                 :            : 
     227                 :         16 :   name = xrealloc (name, namelen + 1);
     228                 :         16 :   name[namelen] = '\0';
     229                 :            : 
     230         [ +  - ]:         16 :   if (out)
     231                 :         16 :     *out = name;
     232                 :            :   else
     233                 :          0 :     free (name);
     234         [ +  + ]:         16 :   if (outlen)
     235                 :          8 :     *outlen = namelen;
     236                 :            : 
     237                 :         16 :   return SHISHI_OK;
     238                 :            : }
     239                 :            : 
     240                 :            : /**
     241                 :            :  * shishi_principal_name_realm:
     242                 :            :  * @handle: Shishi library handle create by shishi_init().
     243                 :            :  * @namenode: ASN.1 structure with principal name in @namefield.
     244                 :            :  * @namefield: name of field in @namenode containing principal name.
     245                 :            :  * @realmnode: ASN.1 structure with principal realm in @realmfield.
     246                 :            :  * @realmfield: name of field in @realmnode containing principal realm.
     247                 :            :  * @out: pointer to newly allocated zero terminated string containing
     248                 :            :  *   principal name.  May be %NULL (to only populate @outlen).
     249                 :            :  * @outlen: pointer to length of @out on output, excluding terminating
     250                 :            :  *   zero.  May be %NULL (to only populate @out).
     251                 :            :  *
     252                 :            :  * Represent principal name and realm in ASN.1 structure as
     253                 :            :  * zero-terminated string.  The string is allocate by this function,
     254                 :            :  * and it is the responsibility of the caller to deallocate it.  Note
     255                 :            :  * that the output length @outlen does not include the terminating
     256                 :            :  * zero.
     257                 :            :  *
     258                 :            :  * Return value: Returns SHISHI_OK iff successful.
     259                 :            :  **/
     260                 :            : int
     261                 :          3 : shishi_principal_name_realm (Shishi * handle,
     262                 :            :                              Shishi_asn1 namenode,
     263                 :            :                              const char *namefield,
     264                 :            :                              Shishi_asn1 realmnode,
     265                 :            :                              const char *realmfield,
     266                 :            :                              char **out, size_t * outlen)
     267                 :            : {
     268                 :            :   char *tmp;
     269                 :            :   size_t tmplen;
     270                 :            :   int rc;
     271                 :            : 
     272                 :          3 :   rc = shishi_principal_name (handle, namenode, namefield, &tmp, &tmplen);
     273         [ -  + ]:          3 :   if (rc != SHISHI_OK)
     274                 :          0 :     return rc;
     275                 :            : 
     276 [ -  + ][ #  # ]:          3 :   if (realmnode == NULL && realmfield)
     277                 :            :     {
     278                 :          0 :       size_t realmfieldlen = strlen (realmfield);
     279                 :            : 
     280                 :          0 :       tmp = xrealloc (tmp, tmplen + 1 + realmfieldlen + 1);
     281                 :            : 
     282                 :          0 :       tmp[tmplen] = '@';
     283                 :          0 :       memcpy (tmp + tmplen + 1, realmfield, realmfieldlen);
     284                 :            : 
     285                 :          0 :       tmplen += 1 + realmfieldlen;
     286                 :            : 
     287                 :          0 :       tmp[tmplen] = '\0';
     288                 :            :     }
     289         [ +  - ]:          3 :   else if (realmnode != NULL)
     290                 :            :     {
     291                 :            :       char *realm;
     292                 :            :       size_t realmlen;
     293                 :            : 
     294                 :          3 :       rc = shishi_asn1_read (handle, realmnode, realmfield,
     295                 :            :                              &realm, &realmlen);
     296         [ -  + ]:          3 :       if (rc != SHISHI_OK)
     297                 :            :         {
     298                 :          0 :           free (tmp);
     299                 :          0 :           return rc;
     300                 :            :         }
     301                 :            : 
     302                 :          3 :       tmp = xrealloc (tmp, tmplen + 1 + realmlen + 1);
     303                 :            : 
     304                 :          3 :       tmp[tmplen] = '@';
     305                 :          3 :       memcpy (tmp + tmplen + 1, realm, realmlen);
     306                 :            : 
     307                 :          3 :       tmplen += 1 + realmlen;
     308                 :            : 
     309                 :          3 :       tmp[tmplen] = '\0';
     310                 :            : 
     311                 :          3 :       free (realm);
     312                 :            :     }
     313                 :            : 
     314                 :          3 :   *out = tmp;
     315         [ +  - ]:          3 :   if (outlen)
     316                 :          3 :     *outlen = tmplen;
     317                 :            : 
     318                 :          3 :   return SHISHI_OK;
     319                 :            : }
     320                 :            : 
     321                 :            : /**
     322                 :            :  * shishi_principal_name_set:
     323                 :            :  * @handle: shishi handle as allocated by shishi_init().
     324                 :            :  * @namenode: ASN.1 structure with principal in @namefield.
     325                 :            :  * @namefield: name of field in namenode containing principal name.
     326                 :            :  * @name_type: type of principial, see Shishi_name_type, usually
     327                 :            :  *             SHISHI_NT_UNKNOWN.
     328                 :            :  * @name: zero-terminated input array with principal name.
     329                 :            :  *
     330                 :            :  * Set the given principal name field to given name.
     331                 :            :  *
     332                 :            :  * Return value: Returns SHISHI_OK iff successful.
     333                 :            :  **/
     334                 :            : int
     335                 :          5 : shishi_principal_name_set (Shishi * handle,
     336                 :            :                            Shishi_asn1 namenode,
     337                 :            :                            const char *namefield,
     338                 :            :                            Shishi_name_type name_type, const char *name[])
     339                 :            : {
     340                 :            :   int res;
     341                 :            :   char *asn1name;
     342                 :            :   int i;
     343                 :            : 
     344                 :          5 :   asprintf (&asn1name, "%s.name-type", namefield);
     345                 :          5 :   res = shishi_asn1_write_int32 (handle, namenode, asn1name, name_type);
     346                 :          5 :   free (asn1name);
     347         [ -  + ]:          5 :   if (res != SHISHI_OK)
     348                 :          0 :     return res;
     349                 :            : 
     350                 :          5 :   asprintf (&asn1name, "%s.name-string", namefield);
     351                 :          5 :   res = shishi_asn1_write (handle, namenode, asn1name, NULL, 0);
     352                 :          5 :   free (asn1name);
     353         [ -  + ]:          5 :   if (res != SHISHI_OK)
     354                 :          0 :     return res;
     355                 :            : 
     356                 :          5 :   i = 1;
     357         [ +  + ]:         12 :   while (name[i - 1])
     358                 :            :     {
     359                 :          7 :       asprintf (&asn1name, "%s.name-string", namefield);
     360                 :          7 :       res = shishi_asn1_write (handle, namenode, asn1name, "NEW", 1);
     361                 :          7 :       free (asn1name);
     362         [ -  + ]:          7 :       if (res != SHISHI_OK)
     363                 :          0 :         return res;
     364                 :            : 
     365                 :          7 :       asprintf (&asn1name, "%s.name-string.?%d", namefield, i);
     366                 :          7 :       res = shishi_asn1_write (handle, namenode, asn1name, name[i - 1], 0);
     367                 :          7 :       free (asn1name);
     368         [ -  + ]:          7 :       if (res != SHISHI_OK)
     369                 :          0 :         return res;
     370                 :            : 
     371                 :          7 :       i++;
     372                 :            :     }
     373                 :            : 
     374                 :          5 :   return SHISHI_OK;
     375                 :            : }
     376                 :            : 
     377                 :            : /**
     378                 :            :  * shishi_principal_set:
     379                 :            :  * @handle: shishi handle as allocated by shishi_init().
     380                 :            :  * @namenode: ASN.1 structure with principal in @namefield.
     381                 :            :  * @namefield: name of field in namenode containing principal name.
     382                 :            :  * @name: zero-terminated string with principal name on RFC 1964 form.
     383                 :            :  *
     384                 :            :  * Set principal name field in ASN.1 structure to given name.
     385                 :            :  *
     386                 :            :  * Return value: Returns SHISHI_OK iff successful.
     387                 :            :  **/
     388                 :            : int
     389                 :          3 : shishi_principal_set (Shishi * handle,
     390                 :            :                       Shishi_asn1 namenode,
     391                 :            :                       const char *namefield, const char *name)
     392                 :            : {
     393                 :            :   char *tmpname;
     394                 :            :   const char **namebuf;
     395                 :          3 :   char *tokptr = NULL;
     396                 :            :   int res;
     397                 :            :   int i;
     398                 :            : 
     399                 :          3 :   tmpname = xstrdup (name);
     400                 :          3 :   namebuf = xmalloc (sizeof (*namebuf));
     401                 :            : 
     402         [ +  + ]:         11 :   for (i = 0;
     403         [ +  + ]:          8 :        (namebuf[i] = strtok_r (i == 0 ? tmpname : NULL, "/", &tokptr)); i++)
     404                 :            :     {
     405                 :          5 :       namebuf = xrealloc (namebuf, (i + 2) * sizeof (*namebuf));
     406                 :            :     }
     407                 :            : 
     408                 :          3 :   res = shishi_principal_name_set (handle, namenode, namefield,
     409                 :            :                                    SHISHI_NT_UNKNOWN, namebuf);
     410                 :          3 :   free (namebuf);
     411                 :          3 :   free (tmpname);
     412         [ -  + ]:          3 :   if (res != SHISHI_OK)
     413                 :            :     {
     414                 :          0 :       shishi_error_printf (handle, _("Could not set principal name: %s\n"),
     415                 :            :                            shishi_strerror (res));
     416                 :          0 :       return res;
     417                 :            :     }
     418                 :            : 
     419                 :          3 :   return SHISHI_OK;
     420                 :            : }
     421                 :            : 
     422                 :            : /**
     423                 :            :  * shishi_derive_default_salt:
     424                 :            :  * @handle: shishi handle as allocated by shishi_init().
     425                 :            :  * @name: principal name of user.
     426                 :            :  * @salt: output variable with newly allocated salt string.
     427                 :            :  *
     428                 :            :  * Derive the default salt from a principal.  The default salt is the
     429                 :            :  * concatenation of the decoded realm and principal.
     430                 :            :  *
     431                 :            :  * Return value: Return SHISHI_OK if successful.
     432                 :            :  **/
     433                 :            : int
     434                 :          0 : shishi_derive_default_salt (Shishi * handle, const char *name, char **salt)
     435                 :            : {
     436                 :            :   char *principal;
     437                 :            :   char *realm;
     438                 :            :   int rc;
     439                 :            : 
     440                 :          0 :   rc = shishi_parse_name (handle, name, &principal, &realm);
     441         [ #  # ]:          0 :   if (rc != SHISHI_OK)
     442                 :          0 :     return rc;
     443                 :            : 
     444 [ #  # ][ #  # ]:          0 :   if (!principal || !realm)
     445                 :            :     {
     446                 :          0 :       free (realm);
     447                 :          0 :       free (principal);
     448                 :          0 :       return SHISHI_INVALID_PRINCIPAL_NAME;
     449                 :            :     }
     450                 :            : 
     451                 :          0 :   *salt = xasprintf ("%s%s", realm, principal);
     452                 :            : 
     453                 :          0 :   free (realm);
     454                 :          0 :   free (principal);
     455                 :            : 
     456                 :          0 :   return SHISHI_OK;
     457                 :            : }
     458                 :            : 
     459                 :            : /**
     460                 :            :  * shishi_server_for_local_service:
     461                 :            :  * @handle: shishi handle as allocated by shishi_init().
     462                 :            :  * @service: zero terminated string with name of service, e.g., "host".
     463                 :            :  *
     464                 :            :  * Construct a service principal (e.g., "imap/yxa.extuno.com") based
     465                 :            :  * on supplied service name (i.e., "imap") and the system hostname as
     466                 :            :  * returned by hostname() (i.e., "yxa.extundo.com").  The string must
     467                 :            :  * be deallocated by the caller.
     468                 :            :  *
     469                 :            :  * Return value: Return newly allocated service name string.
     470                 :            :  **/
     471                 :            : char *
     472                 :          0 : shishi_server_for_local_service (Shishi * handle, const char *service)
     473                 :            : {
     474                 :            :   char *hostname;
     475                 :            :   char *server;
     476                 :            : 
     477                 :          0 :   hostname = xgethostname ();
     478                 :            : 
     479                 :          0 :   asprintf (&server, "%s/%s", service, hostname);
     480                 :            : 
     481                 :          0 :   free (hostname);
     482                 :            : 
     483                 :          0 :   return server;
     484                 :            : }

Generated by: LCOV version 1.8