Print this page
6862532 "cryptoadm: failed to parse configuration" error
6353443 domestic (crypt) source build leaves stuff it shouldn't
6818180 mac(1) printed "invalid key" error message when user input an invalid passphrase


   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <errno.h>
  27 #include <fcntl.h>
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <strings.h>
  31 #include <time.h>
  32 #include <unistd.h>
  33 #include <locale.h>
  34 #include <sys/types.h>
  35 #include <zone.h>
  36 #include <sys/stat.h>
  37 #include "cryptoadm.h"
  38 
  39 static int err; /* To store errno which may be overwritten by gettext() */
  40 static int build_entrylist(entry_t *, entrylist_t **);
  41 static entry_t *dup_entry(entry_t *);
  42 static mechlist_t *dup_mechlist(mechlist_t *);
  43 static entry_t *getent(char *, entrylist_t *);
  44 static int interpret(char *, entry_t **);
  45 static int parse_sup_dis_list(char *, entry_t *);
  46 
  47 
  48 /*
  49  * Duplicate the mechanism list.  A null pointer is returned if the storage
  50  * space available is insufficient or the input argument is NULL.
  51  */
  52 static mechlist_t *
  53 dup_mechlist(mechlist_t *plist)
  54 {
  55         mechlist_t      *pres = NULL;
  56         mechlist_t      *pcur;
  57         mechlist_t      *ptmp;
  58         int             rc = SUCCESS;
  59 
  60         while (plist != NULL) {
  61                 if (!(ptmp = create_mech(plist->name))) {
  62                         rc = FAILURE;
  63                         break;
  64                 }
  65 


 161                         return (NULL);
 162                 }
 163         }
 164 
 165         return (pent2);
 166 }
 167 
 168 
 169 /*
 170  * This routine parses the disabledlist or the supportedlist of an entry
 171  * in the kcf.conf configuration file.
 172  *
 173  * Arguments:
 174  *      buf: an input argument which is a char string with the format of
 175  *           "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
 176  *      pent: the entry for the disabledlist.  This is an IN/OUT argument.
 177  *
 178  * Return value: SUCCESS or FAILURE.
 179  */
 180 static int
 181 parse_sup_dis_list(char *buf, entry_t *pent)
 182 {
 183         mechlist_t      *pmech = NULL;
 184         mechlist_t      *phead = NULL;
 185         char            *next_token;
 186         char            *value;
 187         int             count;
 188         int             supflag = B_FALSE;
 189         int             disflag = B_FALSE;
 190         int             rc = SUCCESS;
 191 
 192         if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) {
 193                 supflag = B_TRUE;
 194         } else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) {
 195                 disflag = B_TRUE;
 196         } else {
 197                 /* should not come here */
 198                 return (FAILURE);
 199         }
 200 
 201         if (value = strpbrk(buf, SEP_EQUAL)) {
 202                 value++; /* get rid of = */
 203         } else {
 204                 cryptodebug("failed to parse the kcf.conf file.");
 205                 return (FAILURE);
 206         }
 207 
 208         if ((next_token = strtok(value, SEP_COMMA)) == NULL) {
 209                 cryptodebug("failed to parse the kcf.conf file.");
 210                 return (FAILURE);
 211         }
 212 
 213         if ((pmech = create_mech(next_token)) == NULL) {
 214                 return (FAILURE);
 215         }
 216 
 217         if (supflag) {





 218                 pent->suplist = phead = pmech;

 219         } else if (disflag) {





 220                 pent->dislist = phead = pmech;
 221         }

 222 
 223         count = 1;
 224         while (next_token) {
 225                 if (next_token = strtok(NULL, SEP_COMMA)) {
 226                         if ((pmech = create_mech(next_token)) == NULL) {
 227                                 rc = FAILURE;
 228                                 break;
 229                         }
 230                         count++;
 231                         phead->next = pmech;
 232                         phead = phead->next;
 233                 }
 234         }
 235 
 236         if (rc == SUCCESS) {
 237                 if (supflag) {
 238                         pent->sup_count = count;
 239                 } else if (disflag) {
 240                         pent->dis_count = count;
 241                 }
 242         } else {
 243                 free_mechlist(phead);
 244         }
 245 
 246         return (rc);
 247 }
 248 
 249 
 250 /*
 251  * Convert a char string containing a line about a provider
 252  * from kcf.conf into an entry_t structure.
 253  *


 254  * See ent2str(), the reverse of this function, for the format of
 255  * kcf.conf lines.
 256  */
 257 static int
 258 interpret(char *buf, entry_t **ppent)
 259 {
 260         entry_t *pent = NULL;
 261         char    *token1;
 262         char    *token2;
 263         char    *token3;
 264         int     rc;
 265 
 266         /* Get provider name */
 267         if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */
 268                 return (FAILURE);
 269         };
 270 
 271         pent = create_entry(token1);
 272         if (pent == NULL) {
 273                 cryptodebug("out of memory.");
 274                 return (FAILURE);
 275         }
 276 
 277         if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
 278                 /* The entry contains a provider name only */
 279                 free_entry(pent);
 280                 return (FAILURE);
 281         }
 282 
 283         if (strncmp(token2, EF_UNLOAD, strlen(EF_UNLOAD)) == 0) {
 284                 pent->load = B_FALSE; /* cryptoadm unload */
 285                 if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
 286                         /* The entry contains a provider name:unload only */
 287                         free_entry(pent);
 288                         return (FAILURE);

 289                 }
 290         }
 291 
 292         /* need to get token3 first to satisfy nested strtok invocations */






 293         token3 = strtok(NULL, SEP_SEMICOLON); /* optional */
 294 
 295         /* parse supportedlist (or disabledlist if no supportedlist) */
 296         if ((token2 != NULL) && ((rc = parse_sup_dis_list(token2, pent)) !=
 297             SUCCESS)) {
 298                 free_entry(pent);
 299                 return (rc);
 300         }
 301 
 302         /* parse disabledlist (if there's a supportedlist) */
 303         if ((token3 != NULL) && ((rc = parse_sup_dis_list(token3, pent)) !=
 304             SUCCESS)) {
 305                 free_entry(pent);
 306                 return (rc);
 307         }

 308 
 309         *ppent = pent;
 310         return (SUCCESS);
 311 }
 312 
 313 
 314 /*
 315  * Add an entry about a provider from kcf.conf to the end of an entry list.
 316  * If the entry list pplist is NULL, create the linked list with pent as the
 317  * first element.
 318  */
 319 static int
 320 build_entrylist(entry_t *pent, entrylist_t **pplist)
 321 {
 322         entrylist_t     *pentlist;
 323         entrylist_t     *pcur = NULL;
 324 
 325         pentlist = malloc(sizeof (entrylist_t));
 326         if (pentlist == NULL) {
 327                 cryptodebug("out of memory.");


 397 /*
 398  * Free elements in a entrylist_t linked list,
 399  * which lists providers in kcf.conf.
 400  */
 401 void
 402 free_entrylist(entrylist_t *entrylist)
 403 {
 404         entrylist_t *pnext;
 405 
 406         while (entrylist != NULL) {
 407                 pnext = entrylist->next;
 408                 free_entry(entrylist->pent);
 409                 entrylist = pnext;
 410         }
 411 }
 412 
 413 
 414 /*
 415  * Convert an entry to a string.  This routine builds a string for the entry
 416  * to be inserted in the kcf.conf file.  Based on the content of each entry,
 417  * the result string can be one of these 6 forms:
 418  *  - name:supportedlist=m1,m2,...,mj
 419  *  - name:disabledlist=m1,m2,...,mj
 420  *  - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
 421  *

 422  *  - name:unload;supportedlist=m1,m2,...,mj
 423  *  - name:unload;disabledlist=m1,m2,...,mj
 424  *  - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
 425  *
 426  * Note that the caller is responsible for freeing the returned string
 427  * (with free_entry()).
 428  * See interpret() for the reverse of this function: converting a string
 429  * to an entry_t.
 430  */
 431 char *
 432 ent2str(entry_t *pent)
 433 {
 434         char            *buf;
 435         mechlist_t      *pcur = NULL;
 436         boolean_t       semicolon_separator = B_FALSE;
 437 
 438 
 439         if (pent == NULL) {
 440                 return (NULL);
 441         }




   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <errno.h>
  27 #include <fcntl.h>
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <strings.h>
  31 #include <time.h>
  32 #include <unistd.h>
  33 #include <locale.h>
  34 #include <sys/types.h>
  35 #include <zone.h>
  36 #include <sys/stat.h>
  37 #include "cryptoadm.h"
  38 
  39 static int err; /* To store errno which may be overwritten by gettext() */
  40 static int build_entrylist(entry_t *, entrylist_t **);
  41 static entry_t *dup_entry(entry_t *);
  42 static mechlist_t *dup_mechlist(mechlist_t *);
  43 static entry_t *getent(char *, entrylist_t *);
  44 static int interpret(char *, entry_t **);
  45 static int parse_sup_dis_list(const char *buf, entry_t *pent);
  46 
  47 
  48 /*
  49  * Duplicate the mechanism list.  A null pointer is returned if the storage
  50  * space available is insufficient or the input argument is NULL.
  51  */
  52 static mechlist_t *
  53 dup_mechlist(mechlist_t *plist)
  54 {
  55         mechlist_t      *pres = NULL;
  56         mechlist_t      *pcur;
  57         mechlist_t      *ptmp;
  58         int             rc = SUCCESS;
  59 
  60         while (plist != NULL) {
  61                 if (!(ptmp = create_mech(plist->name))) {
  62                         rc = FAILURE;
  63                         break;
  64                 }
  65 


 161                         return (NULL);
 162                 }
 163         }
 164 
 165         return (pent2);
 166 }
 167 
 168 
 169 /*
 170  * This routine parses the disabledlist or the supportedlist of an entry
 171  * in the kcf.conf configuration file.
 172  *
 173  * Arguments:
 174  *      buf: an input argument which is a char string with the format of
 175  *           "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
 176  *      pent: the entry for the disabledlist.  This is an IN/OUT argument.
 177  *
 178  * Return value: SUCCESS or FAILURE.
 179  */
 180 static int
 181 parse_sup_dis_list(const char *buf, entry_t *pent)
 182 {
 183         mechlist_t      *pmech = NULL;
 184         mechlist_t      *phead = NULL;
 185         char            *next_token;
 186         char            *value;
 187         int             count;
 188         int             supflag = B_FALSE;
 189         int             disflag = B_FALSE;
 190         int             rc = SUCCESS;
 191 
 192         if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) {
 193                 supflag = B_TRUE;
 194         } else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) {
 195                 disflag = B_TRUE;
 196         } else {
 197                 /* should not come here */
 198                 return (FAILURE);
 199         }
 200 
 201         if (value = strpbrk(buf, SEP_EQUAL)) {
 202                 value++; /* get rid of = */
 203         } else {
 204                 cryptodebug("failed to parse the kcf.conf file.");
 205                 return (FAILURE);
 206         }
 207 
 208         if ((next_token = strtok(value, SEP_COMMA)) == NULL) {
 209                 cryptodebug("failed to parse the kcf.conf file.");
 210                 return (FAILURE);
 211         }
 212 
 213         if ((pmech = create_mech(next_token)) == NULL) {
 214                 return (FAILURE);
 215         }
 216 
 217         if (supflag) {
 218                         if (pent->suplist != NULL) {
 219                                 cryptodebug("multiple supportedlist entries "
 220                                     "for a mechanism in file kcf.conf.");
 221                                 return (FAILURE);
 222                         } else {
 223                                 pent->suplist = phead = pmech;
 224                         }
 225         } else if (disflag) {
 226                         if (pent->dislist != NULL) {
 227                                 cryptodebug("multiple disabledlist entries "
 228                                     "for a mechanism in file kcf.conf.");
 229                                 return (FAILURE);
 230                         } else {
 231                                 pent->dislist = phead = pmech;
 232                         }
 233         }
 234 
 235         count = 1;
 236         while (next_token) {
 237                 if (next_token = strtok(NULL, SEP_COMMA)) {
 238                         if ((pmech = create_mech(next_token)) == NULL) {
 239                                 rc = FAILURE;
 240                                 break;
 241                         }
 242                         count++;
 243                         phead->next = pmech;
 244                         phead = phead->next;
 245                 }
 246         }
 247 
 248         if (rc == SUCCESS) {
 249                 if (supflag) {
 250                         pent->sup_count = count;
 251                 } else if (disflag) {
 252                         pent->dis_count = count;
 253                 }
 254         } else {
 255                 free_mechlist(phead);
 256         }
 257 
 258         return (rc);
 259 }
 260 
 261 
 262 /*
 263  * Convert a char string containing a line about a provider
 264  * from kcf.conf into an entry_t structure.
 265  *
 266  * Note: the input string, buf, may be modified by this function.
 267  *
 268  * See ent2str(), the reverse of this function, for the format of
 269  * kcf.conf lines.
 270  */
 271 static int
 272 interpret(char *buf, entry_t **ppent)
 273 {
 274         entry_t *pent = NULL;
 275         char    *token1;
 276         char    *token2;
 277         char    *token3;
 278         int     rc;
 279 
 280         /* Get provider name */
 281         if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */
 282                 return (FAILURE);
 283         };
 284 
 285         pent = create_entry(token1);
 286         if (pent == NULL) {
 287                 cryptodebug("out of memory.");
 288                 return (FAILURE);
 289         }
 290 
 291         if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
 292                 /* The entry contains a provider name only */
 293                 free_entry(pent);
 294                 return (FAILURE);
 295         }
 296 
 297         if (strncmp(token2, EF_UNLOAD, strlen(EF_UNLOAD)) == 0) {
 298                 pent->load = B_FALSE; /* cryptoadm unload */
 299                 token2 = strtok(NULL, SEP_SEMICOLON);
 300                 /*
 301                  * If token2 is NULL, the entry contains a
 302                  * provider name:unload only
 303                  */
 304         }

 305 
 306         if (token2 != NULL) {
 307                 /*
 308                  * Either supportedlist or disabledlist or both are present.
 309                  * Need to call strtok() to get token3 first, as function
 310                  * parse_sup_dis_list() makes strtok() calls on the
 311                  * token2 substring.
 312                  */
 313                 token3 = strtok(NULL, SEP_SEMICOLON); /* optional */
 314 
 315                 /* parse supportedlist (or disabledlist if no supportedlist) */
 316                 if ((rc = parse_sup_dis_list(token2, pent)) != SUCCESS) {

 317                         free_entry(pent);
 318                         return (rc);
 319                 }
 320 
 321                 /* parse disabledlist (if there's a supportedlist) */
 322                 if ((token3 != NULL) && ((rc = parse_sup_dis_list(token3,
 323                     pent)) != SUCCESS)) {
 324                         free_entry(pent);
 325                         return (rc);
 326                 }
 327         }
 328 
 329         *ppent = pent;
 330         return (SUCCESS);
 331 }
 332 
 333 
 334 /*
 335  * Add an entry about a provider from kcf.conf to the end of an entry list.
 336  * If the entry list pplist is NULL, create the linked list with pent as the
 337  * first element.
 338  */
 339 static int
 340 build_entrylist(entry_t *pent, entrylist_t **pplist)
 341 {
 342         entrylist_t     *pentlist;
 343         entrylist_t     *pcur = NULL;
 344 
 345         pentlist = malloc(sizeof (entrylist_t));
 346         if (pentlist == NULL) {
 347                 cryptodebug("out of memory.");


 417 /*
 418  * Free elements in a entrylist_t linked list,
 419  * which lists providers in kcf.conf.
 420  */
 421 void
 422 free_entrylist(entrylist_t *entrylist)
 423 {
 424         entrylist_t *pnext;
 425 
 426         while (entrylist != NULL) {
 427                 pnext = entrylist->next;
 428                 free_entry(entrylist->pent);
 429                 entrylist = pnext;
 430         }
 431 }
 432 
 433 
 434 /*
 435  * Convert an entry to a string.  This routine builds a string for the entry
 436  * to be inserted in the kcf.conf file.  Based on the content of each entry,
 437  * the result string can be one of these 7 forms:
 438  *  - name:supportedlist=m1,m2,...,mj
 439  *  - name:disabledlist=m1,m2,...,mj
 440  *  - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
 441  *
 442  *  - name:unload
 443  *  - name:unload;supportedlist=m1,m2,...,mj
 444  *  - name:unload;disabledlist=m1,m2,...,mj
 445  *  - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
 446  *
 447  * Note that the caller is responsible for freeing the returned string
 448  * (with free_entry()).
 449  * See interpret() for the reverse of this function: converting a string
 450  * to an entry_t.
 451  */
 452 char *
 453 ent2str(entry_t *pent)
 454 {
 455         char            *buf;
 456         mechlist_t      *pcur = NULL;
 457         boolean_t       semicolon_separator = B_FALSE;
 458 
 459 
 460         if (pent == NULL) {
 461                 return (NULL);
 462         }