LCOV - code coverage report
Current view: top level - dirmngr - ldap-parse-uri.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 84 97 86.6 %
Date: 2015-11-05 17:10:59 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* ldap-parse-uri.c - Parse an LDAP URI.
       2             :  * Copyright (C) 2015  g10 Code GmbH
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * GnuPG is free software; you can redistribute it and/or modify
       7             :  * it 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             :  * GnuPG is distributed in the hope that it will be useful,
      12             :  * but 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 this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : 
      22             : #include <gpg-error.h>
      23             : 
      24             : #ifdef HAVE_W32_SYSTEM
      25             : # include "ldap-url.h"
      26             : #else
      27             : # include <ldap.h>
      28             : #endif
      29             : 
      30             : #include "util.h"
      31             : #include "http.h"
      32             : 
      33             : /* Returns 1 if the string is an LDAP URL (begins with ldap:, ldaps:
      34             :    or ldapi:).  */
      35             : int
      36          20 : ldap_uri_p (const char *url)
      37             : {
      38          20 :   char *colon = strchr (url, ':');
      39          20 :   if (! colon)
      40           8 :     return 0;
      41             :   else
      42             :     {
      43          12 :       int offset = (uintptr_t) colon - (uintptr_t) url;
      44             : 
      45          12 :       if (/* All lower case.  */
      46           6 :           (offset == 4 && memcmp (url, "ldap", 4) == 0)
      47           9 :           || (offset == 5
      48           6 :               && (memcmp (url, "ldaps", 5) == 0
      49           3 :                   && memcmp (url, "ldapi", 5) == 0))
      50             :           /* Mixed case.  */
      51           9 :           || ((url[0] == 'l' || url[0] == 'L')
      52           9 :               && (url[1] == 'd' || url[1] == 'D')
      53           9 :               && (url[2] == 'a' || url[2] == 'A')
      54           9 :               && (url[3] == 'p' || url[3] == 'P')
      55           9 :               && (url[4] == ':'
      56           6 :                   || ((url[4] == 's' || url[4] == 'S'
      57           3 :                        || url[4] == 'i' || url[4] == 'i')
      58           6 :                       && url[5] == ':'))))
      59          12 :         return 1;
      60           0 :       return 0;
      61             :     }
      62             : }
      63             : 
      64             : /* Parse a URI and put the result into *purip.  On success the
      65             :    caller must use http_release_parsed_uri() to releases the resources.
      66             : 
      67             :    uri->path is the base DN (or NULL for the default).
      68             :    uri->auth is the bindname (or NULL for none).
      69             :    The uri->query variable "password" is the password.
      70             : 
      71             :    Note: any specified scope, any attributes, any filter and any
      72             :    unknown extensions are simply ignored.  */
      73             : gpg_error_t
      74           6 : ldap_parse_uri (parsed_uri_t *purip, const char *uri)
      75             : {
      76           6 :   gpg_err_code_t err = 0;
      77           6 :   parsed_uri_t puri = NULL;
      78             : 
      79             :   int result;
      80           6 :   LDAPURLDesc *lud = NULL;
      81             : 
      82           6 :   char *scheme = NULL;
      83           6 :   char *host = NULL;
      84           6 :   char *dn = NULL;
      85           6 :   char *bindname = NULL;
      86           6 :   char *password = NULL;
      87             : 
      88             :   char **s;
      89             : 
      90             :   char *buffer;
      91             :   int len;
      92             : 
      93           6 :   result = ldap_url_parse (uri, &lud);
      94           6 :   if (result != 0)
      95             :     {
      96           0 :       log_error ("Unable to parse LDAP uri '%s'\n", uri);
      97           0 :       err = GPG_ERR_GENERAL;
      98           0 :       goto out;
      99             :     }
     100             : 
     101           6 :   scheme = lud->lud_scheme;
     102           6 :   host = lud->lud_host;
     103           6 :   dn = lud->lud_dn;
     104             : 
     105           8 :   for (s = lud->lud_exts; s && *s; s ++)
     106             :     {
     107           2 :       if (strncmp (*s, "bindname=", 9) == 0)
     108             :         {
     109           1 :           if (bindname)
     110           0 :             log_error ("bindname given multiple times in URL '%s', ignoring.\n",
     111             :                        uri);
     112             :           else
     113           1 :             bindname = *s + 9;
     114             :         }
     115           1 :       else if (strncmp (*s, "password=", 9) == 0)
     116             :         {
     117           1 :           if (password)
     118           0 :             log_error ("password given multiple times in URL '%s', ignoring.\n",
     119             :                        uri);
     120             :           else
     121           1 :             password = *s + 9;
     122             :         }
     123             :       else
     124           0 :         log_error ("Unhandled extension (%s) in URL '%s', ignoring.",
     125             :                    *s, uri);
     126             :     }
     127             : 
     128           6 :   len = 0;
     129             : 
     130             : #define add(s) do { if (s) len += strlen (s) + 1; } while (0)
     131             : 
     132           6 :   add (scheme);
     133           6 :   add (host);
     134           6 :   add (dn);
     135           6 :   add (bindname);
     136           6 :   add (password);
     137             : 
     138           6 :   puri = xtrycalloc (1, sizeof *puri + len);
     139           6 :   if (! puri)
     140             :     {
     141           0 :       err = gpg_err_code_from_syserror ();
     142           0 :       goto out;
     143             :     }
     144             : 
     145           6 :   buffer = puri->buffer;
     146             : 
     147             : #define copy(to, s)                             \
     148             :   do                                            \
     149             :     {                                           \
     150             :       if (s)                                    \
     151             :         {                                       \
     152             :           to = buffer;                          \
     153             :           buffer = stpcpy (buffer, s) + 1;      \
     154             :         }                                       \
     155             :     }                                           \
     156             :   while (0)
     157             : 
     158           6 :   copy (puri->scheme, scheme);
     159             :   /* Make sure the scheme is lower case.  */
     160           6 :   ascii_strlwr (puri->scheme);
     161             : 
     162           6 :   copy (puri->host, host);
     163           6 :   copy (puri->path, dn);
     164           6 :   copy (puri->auth, bindname);
     165             : 
     166           6 :   if (password)
     167             :     {
     168           1 :       puri->query = calloc (sizeof (*puri->query), 1);
     169           1 :       if (!puri->query)
     170             :         {
     171           0 :           err = gpg_err_code_from_syserror ();
     172           0 :           goto out;
     173             :         }
     174           1 :       puri->query->name = "password";
     175           1 :       copy (puri->query->value, password);
     176           1 :       puri->query->valuelen = strlen (password) + 1;
     177             :     }
     178             : 
     179           6 :   puri->use_tls = strcmp (puri->scheme, "ldaps") == 0;
     180           6 :   puri->port = lud->lud_port;
     181             : 
     182             :  out:
     183           6 :   if (lud)
     184           6 :     ldap_free_urldesc (lud);
     185             : 
     186           6 :   if (err)
     187             :     {
     188           0 :       if (puri)
     189           0 :         http_release_parsed_uri (puri);
     190             :     }
     191             :   else
     192           6 :     *purip = puri;
     193             : 
     194           6 :   return gpg_err_make (default_errsource, err);
     195             : }
     196             : 
     197             : /* The following characters need to be escaped to be part of an LDAP
     198             :    filter: *, (, ), \, NUL and /.  Note: we don't handle NUL, since a
     199             :    NUL can't be part of a C string.
     200             : 
     201             :    This function always allocates a new string on success.  It is the
     202             :    caller's responsibility to free it.
     203             : */
     204             : char *
     205           4 : ldap_escape_filter (const char *filter)
     206             : {
     207           4 :   int l = strcspn (filter, "*()\\/");
     208           4 :   if (l == strlen (filter))
     209             :     /* Nothing to escape.  */
     210           2 :     return xstrdup (filter);
     211             : 
     212             :   {
     213             :     /* In the worst case we need to escape every letter.  */
     214           2 :     char *escaped = xmalloc (1 + 3 * strlen (filter));
     215             : 
     216             :     /* Indices into filter and escaped.  */
     217           2 :     int filter_i = 0;
     218           2 :     int escaped_i = 0;
     219             : 
     220          16 :     for (filter_i = 0; filter_i < strlen (filter); filter_i ++)
     221             :       {
     222          14 :         switch (filter[filter_i])
     223             :           {
     224             :           case '*':
     225             :           case '(':
     226             :           case ')':
     227             :           case '\\':
     228             :           case '/':
     229           7 :             snprintf (&escaped[escaped_i], 4, "%%%02x",
     230           7 :                      ((const unsigned char *)filter)[filter_i]);
     231           7 :             escaped_i += 3;
     232           7 :             break;
     233             : 
     234             :           default:
     235           7 :             escaped[escaped_i ++] = filter[filter_i];
     236           7 :             break;
     237             :           }
     238             :       }
     239             :     /* NUL terminate it.  */
     240           2 :     escaped[escaped_i] = 0;
     241             : 
     242             :     /* We could shrink escaped to be just escaped_i bytes, but the
     243             :        result will probably be freed very quickly anyways.  */
     244           2 :     return escaped;
     245             :   }
     246             : }

Generated by: LCOV version 1.11