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


Quelle  ocspsig.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/. */


#include "plarena.h"

#include "seccomon.h"
#include "secitem.h"
#include "secasn1.h"
#include "secder.h"
#include "cert.h"
#include "secerr.h"
#include "secoid.h"
#include "sechash.h"
#include "keyhi.h"
#include "cryptohi.h"
#include "ocsp.h"
#include "ocspti.h"
#include "ocspi.h"
#include "pk11pub.h"

extern const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[];
extern const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[];
extern const SEC_ASN1Template ocsp_OCSPResponseTemplate[];

ocspCertStatus *
ocsp_CreateCertStatus(PLArenaPool *arena,
                      ocspCertStatusType status,
                      PRTime revocationTime)
{
    ocspCertStatus *cs;

    if (!arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    switch (status) {
        case ocspCertStatus_good:
        case ocspCertStatus_unknown:
        case ocspCertStatus_revoked:
            break;
        default:
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return NULL;
    }

    cs = PORT_ArenaZNew(arena, ocspCertStatus);
    if (!cs)
        return NULL;
    cs->certStatusType = status;
    switch (status) {
        case ocspCertStatus_good:
            cs->certStatusInfo.goodInfo = SECITEM_AllocItem(arena, NULL, 0);
            if (!cs->certStatusInfo.goodInfo)
                return NULL;
            break;
        case ocspCertStatus_unknown:
            cs->certStatusInfo.unknownInfo = SECITEM_AllocItem(arena, NULL, 0);
            if (!cs->certStatusInfo.unknownInfo)
                return NULL;
            break;
        case ocspCertStatus_revoked:
            cs->certStatusInfo.revokedInfo =
                PORT_ArenaZNew(arena, ocspRevokedInfo);
            if (!cs->certStatusInfo.revokedInfo)
                return NULL;
            cs->certStatusInfo.revokedInfo->revocationReason =
                SECITEM_AllocItem(arena, NULL, 0);
            if (!cs->certStatusInfo.revokedInfo->revocationReason)
                return NULL;
            if (DER_TimeToGeneralizedTimeArena(arena,
                                               &cs->certStatusInfo.revokedInfo->revocationTime,
                                               revocationTime) !=
                SECSuccess)
                return NULL;
            break;
        default:
            PORT_Assert(PR_FALSE);
    }
    return cs;
}

static const SEC_ASN1Template mySEC_EnumeratedTemplate[] = {
    { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
};

static const SEC_ASN1Template mySEC_PointerToEnumeratedTemplate[] = {
    { SEC_ASN1_POINTER, 0, mySEC_EnumeratedTemplate }
};

static const SEC_ASN1Template ocsp_EncodeRevokedInfoTemplate[] = {
    { SEC_ASN1_GENERALIZED_TIME,
      offsetof(ocspRevokedInfo, revocationTime) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(ocspRevokedInfo, revocationReason),
      mySEC_PointerToEnumeratedTemplate },
    { 0 }
};

static const SEC_ASN1Template ocsp_PointerToEncodeRevokedInfoTemplate[] = {
    { SEC_ASN1_POINTER, 0,
      ocsp_EncodeRevokedInfoTemplate }
};

static const SEC_ASN1Template mySEC_NullTemplate[] = {
    { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) }
};

static const SEC_ASN1Template ocsp_CertStatusTemplate[] = {
    { SEC_ASN1_CHOICE, offsetof(ocspCertStatus, certStatusType),
      0, sizeof(ocspCertStatus) },
    { SEC_ASN1_CONTEXT_SPECIFIC | 0,
      0, mySEC_NullTemplate, ocspCertStatus_good },
    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
          SEC_ASN1_CONTEXT_SPECIFIC | 1,
      offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
      ocsp_PointerToEncodeRevokedInfoTemplate, ocspCertStatus_revoked },
    { SEC_ASN1_CONTEXT_SPECIFIC | 2,
      0, mySEC_NullTemplate, ocspCertStatus_unknown },
    { 0 }
};

static const SEC_ASN1Template mySECOID_AlgorithmIDTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(SECAlgorithmID) },
    { SEC_ASN1_OBJECT_ID,
      offsetof(SECAlgorithmID, algorithm) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
      offsetof(SECAlgorithmID, parameters) },
    { 0 }
};

static const SEC_ASN1Template mySEC_AnyTemplate[] = {
    { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
};

static const SEC_ASN1Template mySEC_SequenceOfAnyTemplate[] = {
    { SEC_ASN1_SEQUENCE_OF, 0, mySEC_AnyTemplate }
};

static const SEC_ASN1Template mySEC_PointerToSequenceOfAnyTemplate[] = {
    { SEC_ASN1_POINTER, 0, mySEC_SequenceOfAnyTemplate }
};

static const SEC_ASN1Template mySEC_IntegerTemplate[] = {
    { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) }
};

static const SEC_ASN1Template mySEC_PointerToIntegerTemplate[] = {
    { SEC_ASN1_POINTER, 0, mySEC_IntegerTemplate }
};

static const SEC_ASN1Template mySEC_GeneralizedTimeTemplate[] = {
    { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
};

static const SEC_ASN1Template mySEC_PointerToGeneralizedTimeTemplate[] = {
    { SEC_ASN1_POINTER, 0, mySEC_GeneralizedTimeTemplate }
};

static const SEC_ASN1Template ocsp_myCertIDTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(CERTOCSPCertID) },
    { SEC_ASN1_INLINE,
      offsetof(CERTOCSPCertID, hashAlgorithm),
      mySECOID_AlgorithmIDTemplate },
    { SEC_ASN1_OCTET_STRING,
      offsetof(CERTOCSPCertID, issuerNameHash) },
    { SEC_ASN1_OCTET_STRING,
      offsetof(CERTOCSPCertID, issuerKeyHash) },
    { SEC_ASN1_INTEGER,
      offsetof(CERTOCSPCertID, serialNumber) },
    { 0 }
};

static const SEC_ASN1Template myCERT_CertExtensionTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(CERTCertExtension) },
    { SEC_ASN1_OBJECT_ID,
      offsetof(CERTCertExtension, id) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */
      offsetof(CERTCertExtension, critical) },
    { SEC_ASN1_OCTET_STRING,
      offsetof(CERTCertExtension, value) },
    { 0 }
};

static const SEC_ASN1Template myCERT_SequenceOfCertExtensionTemplate[] = {
    { SEC_ASN1_SEQUENCE_OF, 0, myCERT_CertExtensionTemplate }
};

static const SEC_ASN1Template myCERT_PointerToSequenceOfCertExtensionTemplate[] = {
    { SEC_ASN1_POINTER, 0, myCERT_SequenceOfCertExtensionTemplate }
};

static const SEC_ASN1Template ocsp_mySingleResponseTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(CERTOCSPSingleResponse) },
    { SEC_ASN1_POINTER,
      offsetof(CERTOCSPSingleResponse, certID),
      ocsp_myCertIDTemplate },
    { SEC_ASN1_ANY,
      offsetof(CERTOCSPSingleResponse, derCertStatus) },
    { SEC_ASN1_GENERALIZED_TIME,
      offsetof(CERTOCSPSingleResponse, thisUpdate) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(CERTOCSPSingleResponse, nextUpdate),
      mySEC_PointerToGeneralizedTimeTemplate },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
      offsetof(CERTOCSPSingleResponse, singleExtensions),
      myCERT_PointerToSequenceOfCertExtensionTemplate },
    { 0 }
};

static const SEC_ASN1Template ocsp_myResponseDataTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(ocspResponseData) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(ocspResponseData, version),
      mySEC_PointerToIntegerTemplate },
    { SEC_ASN1_ANY,
      offsetof(ocspResponseData, derResponderID) },
    { SEC_ASN1_GENERALIZED_TIME,
      offsetof(ocspResponseData, producedAt) },
    { SEC_ASN1_SEQUENCE_OF,
      offsetof(ocspResponseData, responses),
      ocsp_mySingleResponseTemplate },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
      offsetof(ocspResponseData, responseExtensions),
      myCERT_PointerToSequenceOfCertExtensionTemplate },
    { 0 }
};

static const SEC_ASN1Template ocsp_EncodeBasicOCSPResponseTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(ocspBasicOCSPResponse) },
    { SEC_ASN1_POINTER,
      offsetof(ocspBasicOCSPResponse, tbsResponseData),
      ocsp_myResponseDataTemplate },
    { SEC_ASN1_INLINE,
      offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
      mySECOID_AlgorithmIDTemplate },
    { SEC_ASN1_BIT_STRING,
      offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
      offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
      mySEC_PointerToSequenceOfAnyTemplate },
    { 0 }
};

static CERTOCSPSingleResponse *
ocsp_CreateSingleResponse(PLArenaPool *arena,
                          CERTOCSPCertID *id, ocspCertStatus *status,
                          PRTime thisUpdate, const PRTime *nextUpdate)
{
    CERTOCSPSingleResponse *sr;

    if (!arena || !id || !status) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    sr = PORT_ArenaZNew(arena, CERTOCSPSingleResponse);
    if (!sr)
        return NULL;
    sr->arena = arena;
    sr->certID = id;
    sr->certStatus = status;
    if (DER_TimeToGeneralizedTimeArena(arena, &sr->thisUpdate, thisUpdate) !=
        SECSuccess)
        return NULL;
    sr->nextUpdate = NULL;
    if (nextUpdate) {
        sr->nextUpdate = SECITEM_AllocItem(arena, NULL, 0);
        if (!sr->nextUpdate)
            return NULL;
        if (DER_TimeToGeneralizedTimeArena(arena, sr->nextUpdate, *nextUpdate) !=
            SECSuccess)
            return NULL;
    }

    sr->singleExtensions = PORT_ArenaNewArray(arena, CERTCertExtension *, 1);
    if (!sr->singleExtensions)
        return NULL;

    sr->singleExtensions[0] = NULL;

    if (!SEC_ASN1EncodeItem(arena, &sr->derCertStatus,
                            status, ocsp_CertStatusTemplate))
        return NULL;

    return sr;
}

CERTOCSPSingleResponse *
CERT_CreateOCSPSingleResponseGood(PLArenaPool *arena,
                                  CERTOCSPCertID *id,
                                  PRTime thisUpdate,
                                  const PRTime *nextUpdate)
{
    ocspCertStatus *cs;
    if (!arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }
    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_good, 0);
    if (!cs)
        return NULL;
    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
}

CERTOCSPSingleResponse *
CERT_CreateOCSPSingleResponseUnknown(PLArenaPool *arena,
                                     CERTOCSPCertID *id,
                                     PRTime thisUpdate,
                                     const PRTime *nextUpdate)
{
    ocspCertStatus *cs;
    if (!arena) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }
    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_unknown, 0);
    if (!cs)
        return NULL;
    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
}

CERTOCSPSingleResponse *
CERT_CreateOCSPSingleResponseRevoked(
    PLArenaPool *arena,
    CERTOCSPCertID *id,
    PRTime thisUpdate,
    const PRTime *nextUpdate,
    PRTime revocationTime,
    const CERTCRLEntryReasonCode *revocationReason)
{
    ocspCertStatus *cs;
    /* revocationReason is not yet supported, so it must be NULL. */
    if (!arena || revocationReason) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }
    cs = ocsp_CreateCertStatus(arena, ocspCertStatus_revoked, revocationTime);
    if (!cs)
        return NULL;
    return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate);
}

/* responderCert == 0 means:
 * create a response with an invalid signature (for testing purposes) */

SECItem *
CERT_CreateEncodedOCSPSuccessResponse(
    PLArenaPool *arena,
    CERTCertificate *responderCert,
    CERTOCSPResponderIDType responderIDType,
    PRTime producedAt,
    CERTOCSPSingleResponse **responses,
    void *wincx)
{
    PLArenaPool *tmpArena;
    ocspResponseData *rd = NULL;
    ocspResponderID *rid = NULL;
    const SEC_ASN1Template *responderIDTemplate = NULL;
    ocspBasicOCSPResponse *br = NULL;
    ocspResponseBytes *rb = NULL;
    CERTOCSPResponse *response = NULL;

    SECOidTag algID;
    SECOidData *od = NULL;
    SECKEYPrivateKey *privKey = NULL;
    SECItem *result = NULL;

    if (!arena || !responses) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }
    if (responderIDType != ocspResponderID_byName &&
        responderIDType != ocspResponderID_byKey) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }

    tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!tmpArena)
        return NULL;

    rd = PORT_ArenaZNew(tmpArena, ocspResponseData);
    if (!rd)
        goto done;
    rid = PORT_ArenaZNew(tmpArena, ocspResponderID);
    if (!rid)
        goto done;
    br = PORT_ArenaZNew(tmpArena, ocspBasicOCSPResponse);
    if (!br)
        goto done;
    rb = PORT_ArenaZNew(tmpArena, ocspResponseBytes);
    if (!rb)
        goto done;
    response = PORT_ArenaZNew(tmpArena, CERTOCSPResponse);
    if (!response)
        goto done;

    rd->version.data = NULL;
    rd->version.len = 0;
    rd->responseExtensions = NULL;
    rd->responses = responses;
    if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt) !=
        SECSuccess)
        goto done;

    if (!responderCert) {
        /* use invalid signature for testing purposes */
        unsigned char dummyChar = 'd';
        SECItem dummy;

        dummy.len = 1;
        dummy.data = &dummyChar;

        /* it's easier to produdce a keyHash out of nowhere,
         * than to produce an encoded subject,
         * so for our dummy response we always use byKey
         */


        rid->responderIDType = ocspResponderID_byKey;
        if (!ocsp_DigestValue(tmpArena, SEC_OID_SHA1, &rid->responderIDValue.keyHash,
                              &dummy))
            goto done;

        if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid,
                                ocsp_ResponderIDByKeyTemplate))
            goto done;

        br->tbsResponseData = rd;

        if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData,
                                ocsp_myResponseDataTemplate))
            goto done;

        br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem *, 1);
        if (!br->responseSignature.derCerts)
            goto done;
        br->responseSignature.derCerts[0] = NULL;

        algID = SEC_GetSignatureAlgorithmOidTag(rsaKey, SEC_OID_SHA1);
        if (algID == SEC_OID_UNKNOWN)
            goto done;

        /* match the regular signature code, which doesn't use the arena */
        if (!SECITEM_AllocItem(NULL, &br->responseSignature.signature, 1))
            goto done;
        PORT_Memcpy(br->responseSignature.signature.data, &dummyChar, 1);

        /* convert len-in-bytes to len-in-bits */
        br->responseSignature.signature.len = br->responseSignature.signature.len << 3;
    } else {
        rid->responderIDType = responderIDType;
        if (responderIDType == ocspResponderID_byName) {
            responderIDTemplate = ocsp_ResponderIDByNameTemplate;
            if (CERT_CopyName(tmpArena, &rid->responderIDValue.name,
                              &responderCert->subject) != SECSuccess)
                goto done;
        } else {
            responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
            if (!CERT_GetSubjectPublicKeyDigest(tmpArena, responderCert,
                                                SEC_OID_SHA1, &rid->responderIDValue.keyHash))
                goto done;
        }

        if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid,
                                responderIDTemplate))
            goto done;

        br->tbsResponseData = rd;

        if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData,
                                ocsp_myResponseDataTemplate))
            goto done;

        br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem *, 1);
        if (!br->responseSignature.derCerts)
            goto done;
        br->responseSignature.derCerts[0] = NULL;

        privKey = PK11_FindKeyByAnyCert(responderCert, wincx);
        if (!privKey)
            goto done;

        algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1);
        if (algID == SEC_OID_UNKNOWN)
            goto done;

        if (SEC_SignData(&br->responseSignature.signature,
                         br->tbsResponseDataDER.data, br->tbsResponseDataDER.len,
                         privKey, algID) !=
            SECSuccess)
            goto done;

        /* convert len-in-bytes to len-in-bits */
        br->responseSignature.signature.len = br->responseSignature.signature.len << 3;

        /* br->responseSignature.signature wasn't allocated from arena,
         * we must free it when done. */

    }

    if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorithm, algID, 0) !=
        SECSuccess)
        goto done;

    if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br,
                            ocsp_EncodeBasicOCSPResponseTemplate))
        goto done;

    rb->responseTypeTag = SEC_OID_PKIX_OCSP_BASIC_RESPONSE;

    od = SECOID_FindOIDByTag(rb->responseTypeTag);
    if (!od)
        goto done;

    rb->responseType = od->oid;
    rb->decodedResponse.basic = br;

    response->arena = tmpArena;
    response->responseBytes = rb;
    response->statusValue = ocspResponse_successful;

    if (!SEC_ASN1EncodeInteger(tmpArena, &response->responseStatus,
                               response->statusValue))
        goto done;

    result = SEC_ASN1EncodeItem(arena, NULL, response, ocsp_OCSPResponseTemplate);

done:
    if (privKey)
        SECKEY_DestroyPrivateKey(privKey);
    if (br && br->responseSignature.signature.data)
        SECITEM_FreeItem(&br->responseSignature.signature, PR_FALSE);
    PORT_FreeArena(tmpArena, PR_FALSE);

    return result;
}

static const SEC_ASN1Template ocsp_OCSPErrorResponseTemplate[] = {
    { SEC_ASN1_SEQUENCE,
      0, NULL, sizeof(CERTOCSPResponse) },
    { SEC_ASN1_ENUMERATED,
      offsetof(CERTOCSPResponse, responseStatus) },
    { 0, 0,
      mySEC_NullTemplate },
    { 0 }
};

SECItem *
CERT_CreateEncodedOCSPErrorResponse(PLArenaPool *arena, int error)
{
    CERTOCSPResponse response;
    SECItem *result = NULL;

    switch (error) {
        case SEC_ERROR_OCSP_MALFORMED_REQUEST:
            response.statusValue = ocspResponse_malformedRequest;
            break;
        case SEC_ERROR_OCSP_SERVER_ERROR:
            response.statusValue = ocspResponse_internalError;
            break;
        case SEC_ERROR_OCSP_TRY_SERVER_LATER:
            response.statusValue = ocspResponse_tryLater;
            break;
        case SEC_ERROR_OCSP_REQUEST_NEEDS_SIG:
            response.statusValue = ocspResponse_sigRequired;
            break;
        case SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST:
            response.statusValue = ocspResponse_unauthorized;
            break;
        default:
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return NULL;
    }

    if (!SEC_ASN1EncodeInteger(NULL, &response.responseStatus,
                               response.statusValue))
        return NULL;

    result = SEC_ASN1EncodeItem(arena, NULL, &response,
                                ocsp_OCSPErrorResponseTemplate);

    SECITEM_FreeItem(&response.responseStatus, PR_FALSE);

    return result;
}

Messung V0.5
C=99 H=78 G=88

¤ Dauer der Verarbeitung: 0.2 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