LCOV - code coverage report
Current view: top level - lib - error.c (source / functions) Hit Total Coverage
Test: GNU Generic Security Service Lines: 28 63 44.4 %
Date: 2010-05-20 Functions: 1 1 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 15 47 31.9 %

           Branch data     Line data    Source code
       1                 :            : /* error.c --- Error handling functionality.
       2                 :            :  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010  Simon Josefsson
       3                 :            :  *
       4                 :            :  * This file is part of the Generic Security Service (GSS).
       5                 :            :  *
       6                 :            :  * GSS 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                 :            :  * GSS is distributed in the hope that it will be useful, but WITHOUT
      12                 :            :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      13                 :            :  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      14                 :            :  * License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with GSS; if not, see http://www.gnu.org/licenses or write to
      18                 :            :  * 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                 :            : /* _gss_find_mech */
      26                 :            : #include "meta.h"
      27                 :            : 
      28                 :            : struct gss_status_codes
      29                 :            : {
      30                 :            :   gss_uint32 err;
      31                 :            :   const char *name;
      32                 :            :   const char *text;
      33                 :            : };
      34                 :            : 
      35                 :            : static struct gss_status_codes gss_calling_errors[] = {
      36                 :            :   {GSS_S_CALL_INACCESSIBLE_READ, "GSS_S_CALL_INACCESSIBLE_READ",
      37                 :            :    N_("A required input parameter could not be read")},
      38                 :            :   {GSS_S_CALL_INACCESSIBLE_WRITE, "GSS_S_CALL_INACCESSIBLE_WRITE",
      39                 :            :    N_("A required output parameter could not be written")},
      40                 :            :   {GSS_S_CALL_BAD_STRUCTURE, "GSS_S_CALL_BAD_STRUCTURE",
      41                 :            :    N_("A parameter was malformed")}
      42                 :            : };
      43                 :            : 
      44                 :            : static struct gss_status_codes gss_routine_errors[] = {
      45                 :            :   {GSS_S_BAD_MECH, "GSS_S_BAD_MECH",
      46                 :            :    N_("An unsupported mechanism was requested")},
      47                 :            :   {GSS_S_BAD_NAME, "GSS_S_BAD_NAME",
      48                 :            :    N_("An invalid name was supplied")},
      49                 :            :   {GSS_S_BAD_NAMETYPE, "GSS_S_BAD_NAMETYPE",
      50                 :            :    N_("A supplied name was of an unsupported type")},
      51                 :            :   {GSS_S_BAD_BINDINGS, "GSS_S_BAD_BINDINGS",
      52                 :            :    N_("Incorrect channel bindings were supplied")},
      53                 :            :   {GSS_S_BAD_STATUS, "GSS_S_BAD_STATUS",
      54                 :            :    N_("An invalid status code was supplied")},
      55                 :            :   {GSS_S_BAD_SIG, "GSS_S_BAD_SIG",
      56                 :            :    N_("A token had an invalid MIC")},
      57                 :            :   {GSS_S_NO_CRED, "GSS_S_NO_CRED",
      58                 :            :    N_("No credentials were supplied, or the credentials were unavailable "
      59                 :            :       "or inaccessible")},
      60                 :            :   {GSS_S_NO_CONTEXT, "GSS_S_NO_CONTEXT",
      61                 :            :    N_("No context has been established")},
      62                 :            :   {GSS_S_DEFECTIVE_TOKEN, "GSS_S_DEFECTIVE_TOKEN",
      63                 :            :    N_("A token was invalid")},
      64                 :            :   {GSS_S_DEFECTIVE_CREDENTIAL, "GSS_S_DEFECTIVE_CREDENTIAL",
      65                 :            :    N_("A credential was invalid")},
      66                 :            :   {GSS_S_CREDENTIALS_EXPIRED, "GSS_S_CREDENTIALS_EXPIRED",
      67                 :            :    N_("The referenced credentials have expired")},
      68                 :            :   {GSS_S_CONTEXT_EXPIRED, "GSS_S_CONTEXT_EXPIRED",
      69                 :            :    N_("The context has expired")},
      70                 :            :   {GSS_S_FAILURE, "GSS_S_FAILURE",
      71                 :            :    N_("Unspecified error in underlying mechanism")},
      72                 :            :   {GSS_S_BAD_QOP, "GSS_S_BAD_QOP",
      73                 :            :    N_("The quality-of-protection requested could not be provided")},
      74                 :            :   {GSS_S_UNAUTHORIZED, "GSS_S_UNAUTHORIZED",
      75                 :            :    N_("The operation is forbidden by local security policy")},
      76                 :            :   {GSS_S_UNAVAILABLE, "GSS_S_UNAVAILABLE",
      77                 :            :    N_("The operation or option is unavailable")},
      78                 :            :   {GSS_S_DUPLICATE_ELEMENT, "GSS_S_DUPLICATE_ELEMENT",
      79                 :            :    N_("The requested credential element already exists")},
      80                 :            :   {GSS_S_NAME_NOT_MN, "GSS_S_NAME_NOT_MN",
      81                 :            :    N_("The provided name was not a mechanism name")}
      82                 :            : };
      83                 :            : 
      84                 :            : static struct gss_status_codes gss_supplementary_errors[] = {
      85                 :            :   {GSS_S_CONTINUE_NEEDED, "GSS_S_CONTINUE_NEEDED",
      86                 :            :    N_("The gss_init_sec_context() or gss_accept_sec_context() function "
      87                 :            :       "must be called again to complete its function")},
      88                 :            :   {GSS_S_DUPLICATE_TOKEN, "GSS_S_DUPLICATE_TOKEN",
      89                 :            :    N_("The token was a duplicate of an earlier token")},
      90                 :            :   {GSS_S_OLD_TOKEN, "GSS_S_OLD_TOKEN",
      91                 :            :    N_("The token's validity period has expired")},
      92                 :            :   {GSS_S_UNSEQ_TOKEN, "GSS_S_UNSEQ_TOKEN",
      93                 :            :    N_("A later token has already been processed")},
      94                 :            :   {GSS_S_GAP_TOKEN, "GSS_S_GAP_TOKEN",
      95                 :            :    N_("An expected per-message token was not received")}
      96                 :            : };
      97                 :            : 
      98                 :            : /**
      99                 :            :  * gss_display_status:
     100                 :            :  * @minor_status: (integer, modify) Mechanism specific status code.
     101                 :            :  * @status_value: (Integer, read) Status value to be converted.
     102                 :            :  * @status_type: (Integer, read) GSS_C_GSS_CODE - status_value is a
     103                 :            :  *   GSS status code. GSS_C_MECH_CODE - status_value is a mechanism
     104                 :            :  *   status code.
     105                 :            :  * @mech_type: (Object ID, read, optional) Underlying mechanism (used
     106                 :            :  *   to interpret a minor status value). Supply GSS_C_NO_OID to obtain
     107                 :            :  *   the system default.
     108                 :            :  * @message_context: (Integer, read/modify) Should be initialized to
     109                 :            :  *   zero by the application prior to the first call.  On return from
     110                 :            :  *   gss_display_status(), a non-zero status_value parameter indicates
     111                 :            :  *   that additional messages may be extracted from the status code
     112                 :            :  *   via subsequent calls to gss_display_status(), passing the same
     113                 :            :  *   status_value, status_type, mech_type, and message_context
     114                 :            :  *   parameters.
     115                 :            :  * @status_string: (buffer, character string, modify) Textual
     116                 :            :  *   interpretation of the status_value.  Storage associated with this
     117                 :            :  *   parameter must be freed by the application after use with a call
     118                 :            :  *   to gss_release_buffer().
     119                 :            :  *
     120                 :            :  * Allows an application to obtain a textual representation of a
     121                 :            :  * GSS-API status code, for display to the user or for logging
     122                 :            :  * purposes.  Since some status values may indicate multiple
     123                 :            :  * conditions, applications may need to call gss_display_status
     124                 :            :  * multiple times, each call generating a single text string.  The
     125                 :            :  * message_context parameter is used by gss_display_status to store
     126                 :            :  * state information about which error messages have already been
     127                 :            :  * extracted from a given status_value; message_context must be
     128                 :            :  * initialized to 0 by the application prior to the first call, and
     129                 :            :  * gss_display_status will return a non-zero value in this parameter
     130                 :            :  * if there are further messages to extract.
     131                 :            :  *
     132                 :            :  * The message_context parameter contains all state information
     133                 :            :  * required by gss_display_status in order to extract further messages
     134                 :            :  * from the status_value; even when a non-zero value is returned in
     135                 :            :  * this parameter, the application is not required to call
     136                 :            :  * gss_display_status again unless subsequent messages are desired.
     137                 :            :  * The following code extracts all messages from a given status code
     138                 :            :  * and prints them to stderr:
     139                 :            :  *
     140                 :            :  *
     141                 :            :  * ---------------------------------------------------
     142                 :            :  * OM_uint32 message_context;
     143                 :            :  * OM_uint32 status_code;
     144                 :            :  * OM_uint32 maj_status;
     145                 :            :  * OM_uint32 min_status;
     146                 :            :  * gss_buffer_desc status_string;
     147                 :            :  *
     148                 :            :  *        ...
     149                 :            :  *
     150                 :            :  * message_context = 0;
     151                 :            :  *
     152                 :            :  * do {
     153                 :            :  *   maj_status = gss_display_status (
     154                 :            :  *                   &min_status,
     155                 :            :  *                   status_code,
     156                 :            :  *                   GSS_C_GSS_CODE,
     157                 :            :  *                   GSS_C_NO_OID,
     158                 :            :  *                   &message_context,
     159                 :            :  *                   &status_string)
     160                 :            :  *
     161                 :            :  *   fprintf(stderr,
     162                 :            :  *           "%.*s\n",
     163                 :            :  *          (int)status_string.length,
     164                 :            :  *
     165                 :            :  *          (char *)status_string.value);
     166                 :            :  *
     167                 :            :  *   gss_release_buffer(&min_status, &status_string);
     168                 :            :  *
     169                 :            :  * } while (message_context != 0);
     170                 :            :  * ---------------------------------------------------
     171                 :            :  *
     172                 :            :  * Return value:
     173                 :            :  *
     174                 :            :  * `GSS_S_COMPLETE`: Successful completion.
     175                 :            :  *
     176                 :            :  * `GSS_S_BAD_MECH`: Indicates that translation in accordance with an
     177                 :            :  * unsupported mechanism type was requested.
     178                 :            :  *
     179                 :            :  * `GSS_S_BAD_STATUS`: The status value was not recognized, or the
     180                 :            :  * status type was neither GSS_C_GSS_CODE nor GSS_C_MECH_CODE.
     181                 :            :  **/
     182                 :            : OM_uint32
     183                 :          1 : gss_display_status (OM_uint32 * minor_status,
     184                 :            :                     OM_uint32 status_value,
     185                 :            :                     int status_type,
     186                 :            :                     const gss_OID mech_type,
     187                 :            :                     OM_uint32 * message_context, gss_buffer_t status_string)
     188                 :            : {
     189                 :            :   size_t i;
     190                 :            : 
     191                 :          1 :   bindtextdomain (PACKAGE PO_SUFFIX, LOCALEDIR);
     192                 :            : 
     193         [ +  - ]:          1 :   if (minor_status)
     194                 :          1 :     *minor_status = 0;
     195                 :            : 
     196         [ +  - ]:          1 :   if (message_context)
     197                 :          1 :     status_value &= ~*message_context;
     198                 :            : 
     199      [ +  -  - ]:          1 :   switch (status_type)
     200                 :            :     {
     201                 :            :     case GSS_C_GSS_CODE:
     202         [ +  - ]:          1 :       if (message_context)
     203                 :            :         {
     204                 :          1 :           *message_context |=
     205                 :            :             GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET;
     206         [ +  - ]:          1 :           if ((status_value & ~*message_context) == 0)
     207                 :          1 :             *message_context = 0;
     208                 :            :         }
     209                 :            : 
     210      [ +  -  - ]:          1 :       switch (GSS_ROUTINE_ERROR (status_value))
     211                 :            :         {
     212                 :            :         case 0:
     213                 :            :           break;
     214                 :            : 
     215                 :            :         case GSS_S_BAD_MECH:
     216                 :            :         case GSS_S_BAD_NAME:
     217                 :            :         case GSS_S_BAD_NAMETYPE:
     218                 :            :         case GSS_S_BAD_BINDINGS:
     219                 :            :         case GSS_S_BAD_STATUS:
     220                 :            :         case GSS_S_BAD_SIG:
     221                 :            :         case GSS_S_NO_CRED:
     222                 :            :         case GSS_S_NO_CONTEXT:
     223                 :            :         case GSS_S_DEFECTIVE_TOKEN:
     224                 :            :         case GSS_S_DEFECTIVE_CREDENTIAL:
     225                 :            :         case GSS_S_CREDENTIALS_EXPIRED:
     226                 :            :         case GSS_S_CONTEXT_EXPIRED:
     227                 :            :         case GSS_S_FAILURE:
     228                 :            :         case GSS_S_BAD_QOP:
     229                 :            :         case GSS_S_UNAUTHORIZED:
     230                 :            :         case GSS_S_UNAVAILABLE:
     231                 :            :         case GSS_S_DUPLICATE_ELEMENT:
     232                 :            :         case GSS_S_NAME_NOT_MN:
     233                 :          0 :           status_string->value =
     234                 :          0 :             strdup (_(gss_routine_errors
     235                 :            :                       [(GSS_ROUTINE_ERROR (status_value) >>
     236                 :            :                         GSS_C_ROUTINE_ERROR_OFFSET) - 1].text));
     237         [ #  # ]:          0 :           if (!status_string->value)
     238                 :            :             {
     239         [ #  # ]:          0 :               if (minor_status)
     240                 :          0 :                 *minor_status = ENOMEM;
     241                 :          0 :               return GSS_S_FAILURE;
     242                 :            :             }
     243                 :          0 :           status_string->length = strlen (status_string->value);
     244                 :          0 :           return GSS_S_COMPLETE;
     245                 :            :           break;
     246                 :            : 
     247                 :            :         default:
     248                 :          0 :           return GSS_S_BAD_STATUS;
     249                 :            :           break;
     250                 :            :         }
     251                 :            : 
     252         [ +  - ]:          1 :       if (message_context)
     253                 :            :         {
     254                 :          1 :           *message_context |=
     255                 :            :             GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET;
     256         [ +  - ]:          1 :           if ((status_value & ~*message_context) == 0)
     257                 :          1 :             *message_context = 0;
     258                 :            :         }
     259                 :            : 
     260      [ +  -  - ]:          1 :       switch (GSS_CALLING_ERROR (status_value))
     261                 :            :         {
     262                 :            :         case 0:
     263                 :            :           break;
     264                 :            : 
     265                 :            :         case GSS_S_CALL_INACCESSIBLE_READ:
     266                 :            :         case GSS_S_CALL_INACCESSIBLE_WRITE:
     267                 :            :         case GSS_S_CALL_BAD_STRUCTURE:
     268                 :          0 :           status_string->value =
     269                 :          0 :             strdup (_(gss_calling_errors
     270                 :            :                       [(GSS_CALLING_ERROR (status_value) >>
     271                 :            :                         GSS_C_CALLING_ERROR_OFFSET) - 1].text));
     272         [ #  # ]:          0 :           if (!status_string->value)
     273                 :            :             {
     274         [ #  # ]:          0 :               if (minor_status)
     275                 :          0 :                 *minor_status = ENOMEM;
     276                 :          0 :               return GSS_S_FAILURE;
     277                 :            :             }
     278                 :          0 :           status_string->length = strlen (status_string->value);
     279                 :          0 :           return GSS_S_COMPLETE;
     280                 :            :           break;
     281                 :            : 
     282                 :            :         default:
     283                 :          0 :           return GSS_S_BAD_STATUS;
     284                 :            :           break;
     285                 :            :         }
     286                 :            : 
     287         [ +  + ]:          6 :       for (i = 0; i < sizeof (gss_supplementary_errors) /
     288                 :          5 :            sizeof (gss_supplementary_errors[0]); i++)
     289         [ -  + ]:          5 :         if (gss_supplementary_errors[i].err &
     290                 :            :             GSS_SUPPLEMENTARY_INFO (status_value))
     291                 :            :           {
     292                 :          0 :             status_string->value =
     293                 :          0 :               strdup (_(gss_supplementary_errors[i].text));
     294         [ #  # ]:          0 :             if (!status_string->value)
     295                 :            :               {
     296         [ #  # ]:          0 :                 if (minor_status)
     297                 :          0 :                   *minor_status = ENOMEM;
     298                 :          0 :                 return GSS_S_FAILURE;
     299                 :            :               }
     300                 :          0 :             status_string->length = strlen (status_string->value);
     301                 :          0 :             *message_context |= gss_supplementary_errors[i].err;
     302         [ #  # ]:          0 :             if ((status_value & ~*message_context) == 0)
     303                 :          0 :               *message_context = 0;
     304                 :          0 :             return GSS_S_COMPLETE;
     305                 :            :           }
     306                 :            : 
     307         [ -  + ]:          1 :       if (GSS_SUPPLEMENTARY_INFO (status_value))
     308                 :          0 :         return GSS_S_BAD_STATUS;
     309                 :            : 
     310         [ +  - ]:          1 :       if (message_context)
     311                 :          1 :         *message_context = 0;
     312                 :          1 :       status_string->value = strdup (_("No error"));
     313         [ -  + ]:          1 :       if (!status_string->value)
     314                 :            :         {
     315         [ #  # ]:          0 :           if (minor_status)
     316                 :          0 :             *minor_status = ENOMEM;
     317                 :          0 :           return GSS_S_FAILURE;
     318                 :            :         }
     319                 :          1 :       status_string->length = strlen (status_string->value);
     320                 :            :       break;
     321                 :            : 
     322                 :            :     case GSS_C_MECH_CODE:
     323                 :            :       {
     324                 :            :         _gss_mech_api_t mech;
     325                 :            : 
     326                 :          0 :         mech = _gss_find_mech (mech_type);
     327                 :          0 :         return mech->display_status (minor_status, status_value, status_type,
     328                 :            :                                      mech_type, message_context,
     329                 :            :                                      status_string);
     330                 :            :       }
     331                 :            :       break;
     332                 :            : 
     333                 :            :     default:
     334                 :          1 :       return GSS_S_BAD_STATUS;
     335                 :            :     }
     336                 :            : 
     337                 :          1 :   return GSS_S_COMPLETE;
     338                 :            : }

Generated by: LCOV version 1.8