Blame SOURCES/pemutil.c

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