Blame SOURCES/pemutil.c

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