Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  vfyserv.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/****************************************************************************
 *  SSL client program that tests  a server for proper operation of SSL2,   *
 *  SSL3, and TLS. Test propder certificate installation.                   *
 *                                                                          *
 *  This code was modified from the SSLSample code also kept in the NSS     *
 *  directory.                                                              *
 ****************************************************************************/


#include <stdio.h>
#include <string.h>

#if defined(XP_UNIX)
#include <unistd.h>
#endif

#include "prerror.h"

#include "pk11func.h"
#include "secmod.h"
#include "secitem.h"

#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>

#include "nspr.h"
#include "plgetopt.h"
#include "prio.h"
#include "prnetdb.h"
#include "nss.h"
#include "secutil.h"
#include "ocsp.h"

#include "vfyserv.h"

#define RD_BUF_SIZE (60 * 1024)

extern int ssl3CipherSuites[];
extern int numSSL3CipherSuites;

GlobalThreadMgr threadMGR;
char *certNickname = NULL;
char *hostName = NULL;
secuPWData pwdata = { PW_NONE, 0 };
unsigned short port = 0;
PRBool dumpChain;

static void
Usage(const char *progName)
{
    PRFileDesc *pr_stderr;

    pr_stderr = PR_STDERR;

    PR_fprintf(pr_stderr, "Usage:\n"
                          " %s [-c ] [-o] [-p port] [-d dbdir] [-w password] [-f pwfile]\n"
                          " \t\t[-C cipher(s)] [-l -t ] hostname",
               progName);
    PR_fprintf(pr_stderr, "\nWhere:\n");
    PR_fprintf(pr_stderr,
               " %-13s dump server cert chain into files\n",
               "-c");
    PR_fprintf(pr_stderr,
               " %-13s perform server cert OCSP check\n",
               "-o");
    PR_fprintf(pr_stderr,
               " %-13s server port to be used\n",
               "-p");
    PR_fprintf(pr_stderr,
               " %-13s use security databases in \"dbdir\"\n",
               "-d dbdir");
    PR_fprintf(pr_stderr,
               " %-13s key database password\n",
               "-w password");
    PR_fprintf(pr_stderr,
               " %-13s token password file\n",
               "-f pwfile");
    PR_fprintf(pr_stderr,
               " %-13s communication cipher list\n",
               "-C cipher(s)");
    PR_fprintf(pr_stderr,
               " %-13s OCSP responder location. This location is used to\n"
               " %-13s check status of a server certificate. If not \n"
               " %-13s specified, location will be taken from the AIA\n"
               " %-13s server certificate extension.\n",
               "-l url""""""");
    PR_fprintf(pr_stderr,
               " %-13s OCSP Trusted Responder Cert nickname\n\n",
               "-t nickname");

    exit(1);
}

PRFileDesc *
setupSSLSocket(PRNetAddr *addr)
{
    PRFileDesc *tcpSocket;
    PRFileDesc *sslSocket;
    PRSocketOptionData socketOption;
    PRStatus prStatus;
    SECStatus secStatus;

    tcpSocket = PR_NewTCPSocket();
    if (tcpSocket == NULL) {
        errWarn("PR_NewTCPSocket");
    }

    /* Make the socket blocking. */
    socketOption.option = PR_SockOpt_Nonblocking;
    socketOption.value.non_blocking = PR_FALSE;

    prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
    if (prStatus != PR_SUCCESS) {
        errWarn("PR_SetSocketOption");
        goto loser;
    }

    /* Import the socket into the SSL layer. */
    sslSocket = SSL_ImportFD(NULL, tcpSocket);
    if (!sslSocket) {
        errWarn("SSL_ImportFD");
        goto loser;
    }

    /* Set configuration options. */
    secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
    if (secStatus != SECSuccess) {
        errWarn("SSL_OptionSet:SSL_SECURITY");
        goto loser;
    }

    secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
    if (secStatus != SECSuccess) {
        errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
        goto loser;
    }

    /* Set SSL callback routines. */
    secStatus = SSL_GetClientAuthDataHook(sslSocket,
                                          (SSLGetClientAuthData)myGetClientAuthData,
                                          (void *)certNickname);
    if (secStatus != SECSuccess) {
        errWarn("SSL_GetClientAuthDataHook");
        goto loser;
    }

    secStatus = SSL_AuthCertificateHook(sslSocket,
                                        (SSLAuthCertificate)myAuthCertificate,
                                        (void *)CERT_GetDefaultCertDB());
    if (secStatus != SECSuccess) {
        errWarn("SSL_AuthCertificateHook");
        goto loser;
    }

    secStatus = SSL_BadCertHook(sslSocket,
                                (SSLBadCertHandler)myBadCertHandler, NULL);
    if (secStatus != SECSuccess) {
        errWarn("SSL_BadCertHook");
        goto loser;
    }

    secStatus = SSL_HandshakeCallback(sslSocket,
                                      myHandshakeCallback,
                                      NULL);
    if (secStatus != SECSuccess) {
        errWarn("SSL_HandshakeCallback");
        goto loser;
    }

    return sslSocket;

loser:

    PR_Close(tcpSocket);
    return NULL;
}

const char requestString[] = { "GET /testfile HTTP/1.0\r\n\r\n" };

SECStatus
handle_connection(PRFileDesc *sslSocket, int connection)
{
    int countRead = 0;
    PRInt32 numBytes;
    char *readBuffer;

    readBuffer = PORT_Alloc(RD_BUF_SIZE);
    if (!readBuffer) {
        exitErr("PORT_Alloc");
    }

    /* compose the http request here. */

    numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
    if (numBytes <= 0) {
        errWarn("PR_Write");
        PR_Free(readBuffer);
        readBuffer = NULL;
        return SECFailure;
    }

    /* read until EOF */
    while (PR_TRUE) {
        numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
        if (numBytes == 0) {
            break/* EOF */
        }
        if (numBytes < 0) {
            errWarn("PR_Read");
            break;
        }
        countRead += numBytes;
    }

    printSecurityInfo(stderr, sslSocket);

    PR_Free(readBuffer);
    readBuffer = NULL;

    /* Caller closes the socket. */

    fprintf(stderr,
            "***** Connection %d read %d bytes total.\n",
            connection, countRead);

    return SECSuccess; /* success */
}

#define BYTE(n, i) (((i) >> ((n)*8)) & 0xff)

/* one copy of this function is launched in a separate thread for each
** connection to be made.
*/

SECStatus
do_connects(void *a, int connection)
{
    PRNetAddr *addr = (PRNetAddr *)a;
    PRFileDesc *sslSocket;
    PRHostEnt hostEntry;
    char buffer[PR_NETDB_BUF_SIZE];
    PRStatus prStatus;
    PRIntn hostenum;
    PRInt32 ip;
    SECStatus secStatus;

    /* Set up SSL secure socket. */
    sslSocket = setupSSLSocket(addr);
    if (sslSocket == NULL) {
        errWarn("setupSSLSocket");
        return SECFailure;
    }

    secStatus = SSL_SetPKCS11PinArg(sslSocket, &pwdata);
    if (secStatus != SECSuccess) {
        errWarn("SSL_SetPKCS11PinArg");
        return secStatus;
    }

    secStatus = SSL_SetURL(sslSocket, hostName);
    if (secStatus != SECSuccess) {
        errWarn("SSL_SetURL");
        return secStatus;
    }

    /* Prepare and setup network connection. */
    prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
    if (prStatus != PR_SUCCESS) {
        errWarn("PR_GetHostByName");
        return SECFailure;
    }

    hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
    if (hostenum == -1) {
        errWarn("PR_EnumerateHostEnt");
        return SECFailure;
    }

    ip = PR_ntohl(addr->inet.ip);
    fprintf(stderr,
            "Connecting to host %s (addr %d.%d.%d.%d) on port %d\n",
            hostName, BYTE(3, ip), BYTE(2, ip), BYTE(1, ip),
            BYTE(0, ip), PR_ntohs(addr->inet.port));

    prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
    if (prStatus != PR_SUCCESS) {
        errWarn("PR_Connect");
        return SECFailure;
    }

/* Established SSL connection, ready to send data. */
#if 0
    secStatus = SSL_ForceHandshake(sslSocket);
    if (secStatus != SECSuccess) {
        errWarn("SSL_ForceHandshake");
        return secStatus;
    }
#endif

    secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
    if (secStatus != SECSuccess) {
        errWarn("SSL_ResetHandshake");
        prStatus = PR_Close(sslSocket);
        if (prStatus != PR_SUCCESS) {
            errWarn("PR_Close");
        }
        return secStatus;
    }

    secStatus = handle_connection(sslSocket, connection);
    if (secStatus != SECSuccess) {
        /* error already printed out in handle_connection */
        /* errWarn("handle_connection"); */
        prStatus = PR_Close(sslSocket);
        if (prStatus != PR_SUCCESS) {
            errWarn("PR_Close");
        }
        return secStatus;
    }

    PR_Close(sslSocket);
    return SECSuccess;
}

void
client_main(int connections)
{
    int i;
    SECStatus secStatus;
    PRStatus prStatus;
    PRInt32 rv;
    PRNetAddr addr;
    PRHostEnt hostEntry;
    char buffer[PR_NETDB_BUF_SIZE];

    /* Setup network connection. */
    prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
    if (prStatus != PR_SUCCESS) {
        exitErr("PR_GetHostByName");
    }

    rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
    if (rv < 0) {
        exitErr("PR_EnumerateHostEnt");
    }

    secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
    if (secStatus != SECSuccess) {
        exitErr("launch_thread");
    }

    if (connections > 1) {
        /* wait for the first connection to terminate, then launch the rest. */
        reap_threads(&threadMGR);
        /* Start up the connections */
        for (i = 2; i <= connections; ++i) {
            secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
            if (secStatus != SECSuccess) {
                errWarn("launch_thread");
            }
        }
    }

    reap_threads(&threadMGR);
    destroy_thread_data(&threadMGR);
}

#define HEXCHAR_TO_INT(c, i)                   \
    if (((c) >= '0') && ((c) <= '9')) {        \
        i = (c) - '0';                         \
    } else if (((c) >= 'a') && ((c) <= 'f')) { \
        i = (c) - 'a' + 10;                    \
    } else if (((c) >= 'A') && ((c) <= 'F')) { \
        i = (c) - 'A' + 10;                    \
    } else {                                   \
        Usage(progName);                       \
    }

int
main(int argc, char **argv)
{
    char *certDir = NULL;
    char *progName = NULL;
    int connections = 1;
    char *cipherString = NULL;
    char *respUrl = NULL;
    char *respCertName = NULL;
    SECStatus secStatus;
    PLOptState *optstate;
    PLOptStatus status;
    PRBool doOcspCheck = PR_FALSE;

    /* Call the NSPR initialization routines */
    PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);

    progName = PORT_Strdup(argv[0]);

    hostName = NULL;
    optstate = PL_CreateOptState(argc, argv, "C:cd:f:l:n:p:ot:w:");
    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
        switch (optstate->option) {
            case 'C':
                cipherString = PL_strdup(optstate->value);
                break;
            case 'c':
                dumpChain = PR_TRUE;
                break;
            case 'd':
                certDir = PL_strdup(optstate->value);
                break;
            case 'l':
                respUrl = PL_strdup(optstate->value);
                break;
            case 'p':
                port = PORT_Atoi(optstate->value);
                break;
            case 'o':
                doOcspCheck = PR_TRUE;
                break;
            case 't':
                respCertName = PL_strdup(optstate->value);
                break;
            case 'w':
                pwdata.source = PW_PLAINTEXT;
                pwdata.data = PORT_Strdup(optstate->value);
                break;

            case 'f':
                pwdata.source = PW_FROMFILE;
                pwdata.data = PORT_Strdup(optstate->value);
                break;
            case '\0':
                hostName = PL_strdup(optstate->value);
                break;
            default:
                Usage(progName);
        }
    }

    if (port == 0) {
        port = 443;
    }

    if (port == 0 || hostName == NULL)
        Usage(progName);

    if (doOcspCheck &&
        ((respCertName != NULL && respUrl == NULL) ||
         (respUrl != NULL && respCertName == NULL))) {
        SECU_PrintError(progName, "options -l and -t "
                                  " must be used together");
        Usage(progName);
    }

    PK11_SetPasswordFunc(SECU_GetModulePassword);

    /* Initialize the NSS libraries. */
    if (certDir) {
        secStatus = NSS_Init(certDir);
    } else {
        secStatus = NSS_NoDB_Init(NULL);

        /* load the builtins */
        SECMOD_AddNewModule("Builtins",
                            DLL_PREFIX "nssckbi." DLL_SUFFIX, 0, 0);
    }
    if (secStatus != SECSuccess) {
        exitErr("NSS_Init");
    }
    SECU_RegisterDynamicOids();

    if (doOcspCheck == PR_TRUE) {
        SECStatus rv;
        CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
        if (handle == NULL) {
            SECU_PrintError(progName, "problem getting certdb handle");
            goto cleanup;
        }

        rv = CERT_EnableOCSPChecking(handle);
        if (rv != SECSuccess) {
            SECU_PrintError(progName, "error enabling OCSP checking");
            goto cleanup;
        }

        if (respUrl != NULL) {
            rv = CERT_SetOCSPDefaultResponder(handle, respUrl,
                                              respCertName);
            if (rv != SECSuccess) {
                SECU_PrintError(progName,
                                "error setting default responder");
                goto cleanup;
            }

            rv = CERT_EnableOCSPDefaultResponder(handle);
            if (rv != SECSuccess) {
                SECU_PrintError(progName,
                                "error enabling default responder");
                goto cleanup;
            }
        }
    }

    /* All cipher suites except RSA_NULL_MD5 are enabled by
     * Domestic Policy. */

    NSS_SetDomesticPolicy();
    SSL_CipherPrefSetDefault(TLS_RSA_WITH_NULL_MD5, PR_TRUE);

    /* all the SSL2 and SSL3 cipher suites are enabled by default. */
    if (cipherString) {
        int ndx;

        /* disable all the ciphers, then enable the ones we want. */
        disableAllSSLCiphers();

        while (0 != (ndx = *cipherString++)) {
            int cipher = 0;

            if (ndx == ':') {
                int ctmp = 0;

                HEXCHAR_TO_INT(*cipherString, ctmp)
                cipher |= (ctmp << 12);
                cipherString++;
                HEXCHAR_TO_INT(*cipherString, ctmp)
                cipher |= (ctmp << 8);
                cipherString++;
                HEXCHAR_TO_INT(*cipherString, ctmp)
                cipher |= (ctmp << 4);
                cipherString++;
                HEXCHAR_TO_INT(*cipherString, ctmp)
                cipher |= ctmp;
                cipherString++;
            } else {
                if (!isalpha((unsigned char)ndx))
                    Usage(progName);
                ndx = tolower((unsigned char)ndx) - 'a';
                if (ndx < numSSL3CipherSuites) {
                    cipher = ssl3CipherSuites[ndx];
                }
            }
            if (cipher > 0) {
                SECStatus rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
                if (rv != SECSuccess) {
                    SECU_PrintError(progName,
                                    "error setting cipher default preference");
                    goto cleanup;
                }
            } else {
                Usage(progName);
            }
        }
    }

    client_main(connections);

cleanup:
    if (doOcspCheck) {
        CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
        CERT_DisableOCSPDefaultResponder(handle);
        CERT_DisableOCSPChecking(handle);
    }

    if (NSS_Shutdown() != SECSuccess) {
        exit(1);
    }

    PR_Cleanup();
    PORT_Free(progName);
    return 0;
}

Messung V0.5
C=96 H=79 G=87

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge