decode.c revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* Copyright (c) 1990 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
/* decode.c - ber input decoding routines */
#pragma ident "%Z%%M% %I% %E% SMI"
#include <strings.h>
#include <inttypes.h>
#include <ber_der.h>
#include "kmfber_int.h"
static void
ber_svecfree(char **vals)
{
int i;
return;
}
/*
* Note: kmfber_get_tag() only uses the ber_end and ber_ptr elements of ber.
* kmfkmfber_skip_tag() implementations will need to be changed.
*/
/* return the tag - KMFBER_DEFAULT returned means trouble */
static ber_tag_t
{
unsigned char xbyte;
char *tagp;
int i;
return (KMFBER_DEFAULT);
return ((ber_uint_t)xbyte);
for (i = 1; i < sizeof (ber_int_t); i++) {
return (KMFBER_DEFAULT);
if (! (xbyte & KMFBER_MORE_TAG_MASK))
break;
}
/* tag too big! */
if (i == sizeof (ber_int_t))
return (KMFBER_DEFAULT);
/* want leading, not trailing 0's */
}
/*
* Note: kmfber_skip_tag() only uses the ber_end and ber_ptr elements of ber.
* If that changes, the implementation of kmfber_peek_tag() will need to
* be changed.
*/
{
unsigned char lc;
/*
* Any ber element looks like this: tag length contents.
* Assuming everything's ok, we return the tag byte (we
* can assume a single byte), and return the length in len.
*
* Assumptions:
* 1) definite lengths
* 2) primitive encodings used whenever possible
*/
/*
* First, we read the tag.
*/
return (KMFBER_DEFAULT);
/*
* Next, read the length. The first byte contains the length of
* the length. If bit 8 is set, the length is the long form,
* otherwise it's the short form. We don't allow a length that's
* greater than what we can hold in an unsigned long.
*/
*len = 0;
netlen = 0;
return (KMFBER_DEFAULT);
if (lc & 0x80) {
if (noctets > sizeof (ber_uint_t))
return (KMFBER_DEFAULT);
!= noctets)
return (KMFBER_DEFAULT);
} else {
}
return (tag);
}
/*
* Note: Previously, we passed the "ber" parameter directly to
* kmfber_skip_tag(), saving and restoring the ber_ptr element only.
* We now take advantage of the fact that the only ber structure
* elements touched by kmfber_skip_tag() are ber_end and ber_ptr.
* If that changes, this code must change too.
*/
static ber_tag_t
{
}
static int
{
int i;
/*
* The tag and length have already been stripped off. We should
* be sitting right before len bytes of 2's complement integer,
* ready to be read straight into an int. We may have to sign
* extend after we read it in.
*/
if (len > sizeof (ber_slen_t))
return (-1);
/* read into the low-order bytes of netnum */
return (-1);
/* This sets the required sign extension */
if (len != 0) {
} else {
value = 0;
}
for (i = 0; i < len; i++)
return (len);
}
static ber_tag_t
{
return (KMFBER_DEFAULT);
/*
* len is being demoted to a long here -- possible conversion error
*/
return (KMFBER_DEFAULT);
else
return (tag);
}
static ber_tag_t
{
#ifdef STR_TRANSLATION
char *transbuf;
#endif /* STR_TRANSLATION */
return (KMFBER_DEFAULT);
return (KMFBER_DEFAULT);
/*
* datalen is being demoted to a long here -- possible conversion error
*/
return (KMFBER_DEFAULT);
#ifdef STR_TRANSLATION
++datalen;
0) != 0) {
return (KMFBER_DEFAULT);
}
return (KMFBER_DEFAULT);
}
--datalen;
}
#endif /* STR_TRANSLATION */
return (tag);
}
static ber_tag_t
{
return (KMFBER_DEFAULT);
return (KMFBER_DEFAULT);
/*
* datalen is being demoted to a long here -- possible conversion error
*/
return (KMFBER_DEFAULT);
return (tag);
}
{
return (KMFBER_DEFAULT);
}
return (KMFBER_DEFAULT);
}
return (KMFBER_DEFAULT);
return (tag);
}
{
== NULL) {
return (KMFBER_DEFAULT);
}
return (KMFBER_DEFAULT);
}
== NULL) {
return (KMFBER_DEFAULT);
}
/*
* len is being demoted to a long here -- possible conversion error
*/
return (KMFBER_DEFAULT);
/* If DER encoding, strip leading 0's */
p++;
}
/*
* Shift the buffer to the beginning of the allocated space
* so it can be properly freed later.
*/
}
return (tag);
}
static ber_tag_t
{
== NULL) {
return (KMFBER_DEFAULT);
}
return (KMFBER_DEFAULT);
}
== NULL) {
return (KMFBER_DEFAULT);
}
/*
* len is being demoted to a long here -- possible conversion error
*/
return (KMFBER_DEFAULT);
return (tag);
}
static ber_tag_t
{
unsigned char unusedbits;
return (KMFBER_DEFAULT);
return (KMFBER_DEFAULT);
return (KMFBER_DEFAULT);
/* Subtract 1 for the unused bits */
datalen--;
/*
* datalen is being demoted to a long here -- possible conversion error
*/
return (KMFBER_DEFAULT);
return (tag);
}
static ber_tag_t
{
return (KMFBER_DEFAULT);
if (len != 0)
return (KMFBER_DEFAULT);
return (tag);
}
static ber_tag_t
{
int rc;
return (rc);
}
{
/* skip the sequence header, use the len to mark where to stop */
return (KMFBER_ERROR);
}
return (KMFBER_END_OF_SEQORSET);
}
}
{
return (KMFBER_END_OF_SEQORSET);
}
}
void
{
}
}
}
void
{
int i;
kmfber_bvfree(bv[i]);
}
}
}
/* VARARGS */
{
char *last, *p;
int *i, j;
ber_slen_t *l;
ber_tag_t *t;
switch (*p) {
case 'a': /* octet string - allocate storage as needed */
break;
case 'b': /* boolean */
break;
case 'D': /* Object ID */
break;
case 'e': /* enumerated */
case 'i': /* int */
break;
case 'l': /* length of next item */
break;
case 'n': /* null */
break;
case 's': /* octet string - in a buffer */
break;
case 'o': /* octet string in a supplied berval */
break;
case 'I': /* variable length Integer */
/* Treat INTEGER same as an OCTET string, but ignore the tag */
break;
case 'O': /* octet string - allocate & include length */
break;
case 'B': /* bit string - allocate storage as needed */
break;
case 't': /* tag of next item */
break;
case 'T': /* skip tag of next item */
break;
case 'v': /* sequence of strings */
j = 0;
array_size = 0;
(tag != KMFBER_DEFAULT &&
tag != KMFBER_END_OF_SEQORSET &&
rc != KMFBER_DEFAULT);
/* Make room for at least 15 strings */
array_size = 16;
} else {
/* We'v overflowed our buffer */
(array_size * 2) * sizeof (char *));
}
}
j++;
}
if (rc != KMFBER_DEFAULT &&
tag != KMFBER_END_OF_SEQORSET) {
rc = KMFBER_DEFAULT;
}
if (j > 0)
break;
case 'V': /* sequence of strings + lengths */
j = 0;
(tag != KMFBER_DEFAULT &&
tag != KMFBER_END_OF_SEQORSET &&
rc != KMFBER_DEFAULT);
2 * sizeof (struct berval *));
} else {
(j + 2) * sizeof (struct berval *));
}
j++;
}
if (rc != KMFBER_DEFAULT &&
tag != KMFBER_END_OF_SEQORSET) {
rc = KMFBER_DEFAULT;
}
if (j > 0)
break;
case 'x': /* skip the next element - whatever it is */
break;
break;
case '{': /* begin sequence */
case '[': /* begin set */
if (*(p + 1) != 'v' && *(p + 1) != 'V')
break;
case '}': /* end sequence */
case ']': /* end set */
break;
default:
#ifdef KMFBER_DEBUG
{
char msg[80];
}
#endif
rc = KMFBER_DEFAULT;
break;
}
}
if (rc == KMFBER_DEFAULT) {
switch (*fmt) {
case 'a': /* octet string - allocate storage as needed */
break;
case 'b': /* boolean */
break;
case 'e': /* enumerated */
case 'i': /* int */
break;
case 'l': /* length of next item */
break;
case 'n': /* null */
break;
case 's': /* octet string - in a buffer */
break;
case 'o': /* octet string in a supplied berval */
break;
case 'O': /* octet string - allocate & include length */
kmfber_bvfree(*bvp);
break;
case 'B': /* bit string - allocate storage as needed */
break;
case 't': /* tag of next item */
break;
case 'T': /* skip tag of next item */
break;
case 'v': /* sequence of strings */
ber_svecfree(*sss);
break;
case 'V': /* sequence of strings + lengths */
break;
case 'x': /* skip the next element - whatever it is */
break;
case '{': /* begin sequence */
case '[': /* begin set */
break;
case '}': /* end sequence */
case ']': /* end set */
break;
default:
break;
}
} /* for */
} /* if */
return (rc);
}
struct berval *
{
== NULL) {
return (NULL);
}
} else {
== NULL) {
return (NULL);
}
}
return (new);
}