Blame SOURCES/pemutil.c

b76ddc
/*
b76ddc
   Copyright 2008 Red Hat, Inc.
b76ddc
b76ddc
   This program is free software; you can redistribute it and/or modify
b76ddc
   it under the terms of the GNU General Public License as published by
b76ddc
   the Free Software Foundation; either version 2 of the License, or
b76ddc
   (at your option) any later version.
b76ddc
  
b76ddc
   This program is distributed in the hope that it will be useful,
b76ddc
   but WITHOUT ANY WARRANTY; without even the implied warranty of
b76ddc
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b76ddc
   GNU General Public License for more details.
b76ddc
  
b76ddc
   You should have received a copy of the GNU General Public License
b76ddc
   along with this program; if not, write to the Free Software
b76ddc
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
b76ddc
   
b76ddc
   In addition, as a special exception, Red Hat, Inc. gives permission
b76ddc
   to link the code of this program with the OpenSSL library (or with
b76ddc
   modified versions of OpenSSL that use the same license as OpenSSL),
b76ddc
   and distribute linked combinations including the two. You must obey
b76ddc
   the GNU General Public License in all respects for all of the code
b76ddc
   used other than OpenSSL. If you modify this file, you may extend
b76ddc
   this exception to your version of the file, but you are not
b76ddc
   obligated to do so. If you do not wish to do so, delete this
b76ddc
   exception statement from your version.
b76ddc
b76ddc
*/
b76ddc
b76ddc
/* Certificate processing utilities, based on code from Mozilla
b76ddc
 * Network Security Services internal secutils static library.
b76ddc
 */
b76ddc
b76ddc
/* ***** BEGIN LICENSE BLOCK *****
b76ddc
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
b76ddc
 *
b76ddc
 * The contents of this file are subject to the Mozilla Public License Version
b76ddc
 * 1.1 (the "License"); you may not use this file except in compliance with
b76ddc
 * the License. You may obtain a copy of the License at
b76ddc
 * http://www.mozilla.org/MPL/
b76ddc
 *
b76ddc
 * Software distributed under the License is distributed on an "AS IS" basis,
b76ddc
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
b76ddc
 * for the specific language governing rights and limitations under the
b76ddc
 * License.
b76ddc
 *
b76ddc
 * The Original Code is the Netscape security libraries.
b76ddc
 *
b76ddc
 * The Initial Developer of the Original Code is
b76ddc
 * Netscape Communications Corporation.
b76ddc
 * Portions created by the Initial Developer are Copyright (C) 1994-2000
b76ddc
 * the Initial Developer. All Rights Reserved.
b76ddc
 *
b76ddc
 * Contributor(s):
b76ddc
 *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
b76ddc
 *
b76ddc
 * Alternatively, the contents of this file may be used under the terms of
b76ddc
 * either the GNU General Public License Version 2 or later (the "GPL"), or
b76ddc
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
b76ddc
 * in which case the provisions of the GPL or the LGPL are applicable instead
b76ddc
 * of those above. If you wish to allow use of your version of this file only
b76ddc
 * under the terms of either the GPL or the LGPL, and not to allow others to
b76ddc
 * use your version of this file under the terms of the MPL, indicate your
b76ddc
 * decision by deleting the provisions above and replace them with the notice
b76ddc
 * and other provisions required by the GPL or the LGPL. If you do not delete
b76ddc
 * the provisions above, a recipient may use your version of this file under
b76ddc
 * the terms of any one of the MPL, the GPL or the LGPL.
b76ddc
 *
b76ddc
 * ***** END LICENSE BLOCK ***** */
b76ddc
b76ddc
/*
b76ddc
 * The exported function here is PEMUTIL_PEM_read_X509. A function like
b76ddc
 * this belongs in nss_compat_ossl. Elio Maldonado <emaldona@redhat.com> 
b76ddc
 */
b76ddc
b76ddc
#include <cert.h>
b76ddc
#include <certt.h>
b76ddc
#include <nspr.h>
b76ddc
#include <seccomon.h>
b76ddc
#include <base64.h>
b76ddc
#include <assert.h>
b76ddc
b76ddc
#define TIME_BUF_SIZE 100
b76ddc
b76ddc
/* decode a SECItem containing either a SEC_ASN1_GENERALIZED_TIME 
b76ddc
   or a SEC_ASN1_UTC_TIME */
b76ddc
extern SECStatus DER_DecodeTimeChoice(PRTime* output, const SECItem* input);
b76ddc
b76ddc
b76ddc
/* Loads the contents of a file into a SECItem.
b76ddc
 * Code is from the NSS security utilities.
b76ddc
 */
b76ddc
static SECStatus FileToItem(SECItem *dst, PRFileDesc *src)
b76ddc
{
b76ddc
    PRFileInfo info;
b76ddc
    PRInt32 numBytes;
b76ddc
    PRStatus prStatus;
b76ddc
b76ddc
    prStatus = PR_GetOpenFileInfo(src, &info;;
b76ddc
b76ddc
    if (prStatus != PR_SUCCESS) {
b76ddc
        return SECFailure;
b76ddc
    }
b76ddc
b76ddc
    /* XXX workaround for 3.1, not all utils zero dst before sending */
b76ddc
    dst->data = 0;
b76ddc
    if (!SECITEM_AllocItem(NULL, dst, info.size))
b76ddc
        goto loser;
b76ddc
b76ddc
    numBytes = PR_Read(src, dst->data, info.size);
b76ddc
    if (numBytes != info.size)
b76ddc
        goto loser;
b76ddc
b76ddc
    return SECSuccess;
b76ddc
loser:
b76ddc
    SECITEM_FreeItem(dst, PR_FALSE);
b76ddc
    dst->data = NULL;
b76ddc
    return SECFailure;
b76ddc
}
b76ddc
b76ddc
/* Load a DER encoding into a SECItem.
b76ddc
 * Code is from the NSS security utilities.
b76ddc
 */
b76ddc
static SECStatus ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
b76ddc
{
b76ddc
    SECStatus rv;
b76ddc
    if (ascii) {
b76ddc
        /* First convert ascii to binary */
b76ddc
        SECItem filedata;
b76ddc
        char *asc, *body;
b76ddc
    
b76ddc
        /* Read in ascii data */
b76ddc
        rv = FileToItem(&filedata, inFile);
b76ddc
        asc = (char *)filedata.data;
b76ddc
        if (!asc) {
b76ddc
            return SECFailure;
b76ddc
        }
b76ddc
    
b76ddc
        /* check for headers and trailers and remove them */
b76ddc
        if ((body = strstr(asc, "-----BEGIN")) != NULL) {
b76ddc
            char *trailer = NULL;
b76ddc
            asc = body;
b76ddc
            body = PORT_Strchr(body, '\n');
b76ddc
            if (!body)
b76ddc
                body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
b76ddc
            if (body)
b76ddc
                trailer = strstr(++body, "-----END");
b76ddc
            if (trailer != NULL) {
b76ddc
                *trailer = '\0';
b76ddc
            } else {
b76ddc
                /*printf("input has header but no trailer\n");*/
b76ddc
                PORT_Free(filedata.data);
b76ddc
                return SECFailure;
b76ddc
           }
b76ddc
        } else {
b76ddc
            body = asc;
b76ddc
        }
b76ddc
         
b76ddc
        /* Convert to binary */
b76ddc
        rv = ATOB_ConvertAsciiToItem(der, body);
b76ddc
        if (rv) {
b76ddc
            /* printf("ATOB_ConvertAsciiToItem failed\n");*/
b76ddc
            PORT_Free(filedata.data);
b76ddc
            return SECFailure;
b76ddc
        }
b76ddc
    
b76ddc
        PORT_Free(filedata.data);
b76ddc
    } else {
b76ddc
        /* Read in binary der */
b76ddc
        rv = FileToItem(der, inFile);
b76ddc
        if (rv) {
b76ddc
            return SECFailure;
b76ddc
        }
b76ddc
    }
b76ddc
    return SECSuccess;
b76ddc
}
b76ddc
b76ddc
b76ddc
/* Return a certificate structure from a pem-encoded cert in a file; 
b76ddc
 * or NULL on failure. Semantics similar to an OpenSSL
b76ddc
 * PEM_read_X509(fp, NULL, NULL, NULL); call
b76ddc
 */
b76ddc
CERTCertificate *
b76ddc
PEMUTIL_PEM_read_X509(const char *filename)
b76ddc
{
b76ddc
    CERTCertificate *cert = NULL;
b76ddc
    PRFileDesc *fd = NULL;
b76ddc
    SECItem derCert;
b76ddc
b76ddc
    fd = PR_Open(filename, PR_RDONLY, 0);
b76ddc
    if (!fd) return NULL;
b76ddc
b76ddc
    /* Read in a DER from a file, it is ascii */
b76ddc
    if (SECSuccess != ReadDERFromFile(&derCert, fd, PR_TRUE))
b76ddc
        goto cleanup;
b76ddc
   
b76ddc
    /* create a temporary cert in the database */
b76ddc
    cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 
b76ddc
            &derCert, NULL, PR_FALSE, PR_FALSE);
b76ddc
               /* noNickname, notPerm, noCopy */
b76ddc
 cleanup:
b76ddc
    if (fd) PR_Close(fd);
b76ddc
b76ddc
    return cert;
b76ddc
}