[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271] [0272] [0273] [0274] [0275] [0276] [0277] [0278] [0279] [0280] [0281] [0282] [0283] [0284] [0285] [0286] [0287] [0288] [0289] [0290] [0291] [0292] [0293] [0294] [0295] [0296] [0297] [0298] [0299] [0300] [0301] [0302] [0303] [0304] [0305] [0306] [0307] [0308] [0309] [0310] [0311] [0312] [0313] [0314] [0315] [0316] [0317] [0318] [0319] [0320] [0321] [0322] [0323] [0324] [0325] [0326] [0327] [0328] [0329] [0330] [0331] [0332] [0333] [0334] [0335] [0336] [0337] [0338] [0339] [0340] [0341] [0342] [0343] [0344] [0345] [0346] [0347] [0348] [0349] [0350] [0351] [0352] [0353] [0354] [0355] [0356] [0357] [0358] [0359] [0360] [0361] [0362] [0363] [0364] [0365] [0366] [0367] [0368] [0369] [0370] [0371] [0372] [0373] [0374] [0375] [0376] [0377] [0378] [0379] [0380] [0381] [0382] [0383] [0384] [0385] [0386] [0387] [0388] [0389] [0390] [0391] [0392] [0393] [0394] [0395] [0396] [0397] [0398] [0399] [0400] [0401] [0402] [0403] [0404] [0405] [0406] [0407] [0408] [0409] [0410] [0411] [0412] [0413] [0414] [0415] [0416] [0417] [0418] [0419] [0420] [0421] [0422] [0423] [0424] [0425] [0426] [0427] [0428] [0429] [0430] [0431] [0432] [0433] [0434] [0435] [0436] [0437] [0438] [0439] [0440] [0441] [0442] [0443] [0444] [0445] [0446] [0447] [0448] [0449] [0450] [0451] [0452] [0453] [0454] [0455] [0456] [0457] [0458] [0459] [0460] [0461] [0462] [0463] [0464] [0465] [0466] [0467] [0468] [0469] [0470] [0471] [0472] [0473] [0474] [0475] [0476] [0477] [0478] [0479] [0480] [0481] [0482] [0483] [0484] [0485] [0486] [0487] [0488] [0489] [0490] [0491] [0492] [0493] [0494] [0495] [0496] [0497] [0498] [0499] [0500] [0501] [0502] [0503] [0504] [0505] [0506] [0507] [0508] [0509] [0510] [0511] [0512] [0513] [0514] [0515] [0516] [0517] [0518] [0519] [0520] [0521] [0522] [0523] [0524] [0525] [0526] [0527] [0528] [0529] [0530] [0531] [0532] [0533] [0534] [0535] [0536] [0537] [0538] [0539] [0540] [0541] [0542] [0543] [0544] [0545] [0546] [0547] [0548] [0549] [0550] [0551] [0552] [0553] [0554] [0555] [0556] [0557] [0558] [0559] [0560] [0561] [0562] [0563] [0564] [0565] [0566] [0567] [0568] [0569] [0570] [0571] [0572] [0573] [0574] [0575] [0576] [0577] [0578] [0579] [0580] [0581] [0582] [0583] [0584] [0585] [0586] [0587] [0588] [0589] [0590] [0591] [0592] [0593] [0594] [0595] [0596] [0597] [0598] [0599] [0600] [0601] [0602] [0603] [0604] [0605] [0606] [0607] [0608] [0609] [0610] [0611] [0612] [0613] [0614] [0615] [0616] [0617] [0618] [0619] [0620] [0621] [0622] [0623] [0624] [0625] [0626] [0627] [0628] [0629] [0630] [0631] [0632] [0633] [0634] [0635] [0636] [0637] [0638] [0639] [0640] [0641] [0642] [0643] [0644] [0645] [0646] [0647] [0648] [0649] [0650] [0651] [0652] [0653] [0654] [0655] [0656] [0657] [0658] [0659] [0660] [0661] [0662] [0663] [0664] [0665] [0666] [0667] [0668] [0669] [0670] [0671] [0672] [0673] [0674] [0675] [0676] [0677] [0678] [0679] [0680] [0681] [0682] [0683] [0684] [0685] [0686] [0687] [0688] [0689] [0690] [0691] [0692] [0693] [0694] [0695] [0696] [0697] [0698] [0699] [0700] [0701] [0702] [0703] [0704] [0705] [0706] [0707] [0708] [0709] [0710] [0711] [0712] [0713] [0714] [0715] [0716] [0717] [0718] [0719] [0720] [0721] [0722] [0723] [0724] [0725] [0726] [0727] [0728] [0729] [0730] [0731] [0732] [0733] [0734] [0735] [0736] [0737] [0738] [0739] [0740] [0741] [0742] [0743] [0744] [0745] [0746] [0747] [0748] [0749] [0750] [0751] [0752] [0753] [0754] [0755] [0756] [0757] [0758] [0759] [0760] [0761] [0762] [0763] [0764] [0765] [0766] [0767] [0768] [0769] [0770] [0771] [0772] [0773] [0774] [0775] [0776] [0777] [0778] [0779] [0780] [0781] [0782] [0783] [0784] [0785] [0786] [0787] [0788] [0789] [0790] [0791] [0792] [0793] [0794] [0795] [0796] [0797] [0798] [0799] [0800] [0801] [0802] [0803] [0804] [0805] [0806] [0807] [0808] [0809] [0810] [0811]
/*****************************************************************************/ /* SesolaCGI.c Secure Sockets Layer CGI variables. VERSION HISTORY --------------- 15-MAR-2020 MGD add SSL_TLS_ALPN variable for ALPN protocol list 23-JUL-2016 MGD use SSL_SESSION_get_id() instead of ->session_id.. 27-SEP-2015 MGD SesolaCgiVariablesExtension() document X509 extensions 28-JUL-2013 MGD add Apache SSL_TLS_SNI variable for SNI server name 21-OCT-2001 MGD rework SESOLA.C */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif /* standard C header files */ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* VMS related header files */ #include <ssdef.h> #include <stsdef.h> /* application header files */ #define SESOLA_REQUIRED #include "Sesola.h" #define WASD_MODULE "SESOLACGI" /***************************************/ #ifdef SESOLA /* secure sockets layer */ /***************************************/ /********************/ /* external storage */ /********************/ #ifdef DBUG extern BOOL Debug; #else #define Debug 0 #endif extern int ToLowerCase[], ToUpperCase[]; extern char ErrorSanityCheck[], SoftwareID[]; extern BIO *SesolaBioMemPtr; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* Generate appropriate SSL-related CGI variables. Called from CgiGenerateVariables(). */ int SesolaCgiGenerateVariables ( REQUEST_STRUCT *rqptr, int VarType ) { static $DESCRIPTOR (NumberFaoDsc, "!UL\0"); int status, KeySize; char String [512]; char *cptr; $DESCRIPTOR (StringDsc, String); SESOLA_STRUCT *sesolaptr; SSL *SslPtr; SSL_CIPHER *CipherPtr; X509 *ServerCertPtr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_SESOLA)) WatchThis (WATCHITM(rqptr), WATCH_MOD_SESOLA, "SesolaCgiGenerateVariables() !UL", VarType); if (!(sesolaptr = SesolaRequestSesolaPtr (rqptr))) return (SS$_NORMAL); SslPtr = sesolaptr->SslPtr; CipherPtr = SSL_get_current_cipher (SslPtr); ServerCertPtr = SSL_get_certificate (SslPtr); status = SS$_NORMAL; if (sesolaptr->ClientCertPtr) { if (rqptr->rqAuth.ClientCertFingerprintPtr && rqptr->rqAuth.ClientCertFingerprintPtr[0]) status = CgiVariable (rqptr, "AUTH_X509_FINGERPRINT", rqptr->rqAuth.ClientCertFingerprintPtr, VarType); if (VMSok (status)) if (rqptr->rqAuth.ClientCertIssuerPtr && rqptr->rqAuth.ClientCertIssuerPtr[0]) status = CgiVariable (rqptr, "AUTH_X509_ISSUER", rqptr->rqAuth.ClientCertIssuerPtr, VarType); if (VMSok (status)) if (rqptr->rqAuth.ClientCertSubjectPtr && rqptr->rqAuth.ClientCertSubjectPtr[0]) status = CgiVariable (rqptr, "AUTH_X509_SUBJECT", rqptr->rqAuth.ClientCertSubjectPtr, VarType); if (VMSok (status)) { cptr = (char*)SSL_CIPHER_get_name (CipherPtr); status = CgiVariable (rqptr, "AUTH_X509_CIPHER", cptr, VarType); } if (VMSok (status)) { KeySize = SSL_CIPHER_get_bits (CipherPtr, NULL); sys$fao (&NumberFaoDsc, 0, &StringDsc, KeySize); status = CgiVariable (rqptr, "AUTH_X509_KEYSIZE", String, VarType); } } if (VMSok (status)) { BIO_reset (SesolaBioMemPtr); switch (rqptr->rqPathSet.SSLCGIvar) { case SESOLA_CGI_VAR_APACHE_MOD_SSL : case SESOLA_CGI_VAR_APACHE_MOD_SSL_CLIENT : case SESOLA_CGI_VAR_APACHE_MOD_SSL_EXTENS : case SESOLA_CGI_VAR_APACHE_MOD_SSL_OID : status = SesolaCgiVariablesApacheModSsl (rqptr, VarType); break; case SESOLA_CGI_VAR_PURVEYOR : status = SesolaCgiVariablesPurveyor (rqptr, VarType); break; } BIO_reset (SesolaBioMemPtr); } return (status); } /*****************************************************************************/ /* Generate some Apache mod_SSL style CGI variables. */ int SesolaCgiVariablesApacheModSsl ( REQUEST_STRUCT *rqptr, int VarType ) { static char HexDigits [] = "0123456789abcdef"; static $DESCRIPTOR (NumberFaoDsc, "!UL\0"); int cnt, status, AlgKeySize, ObjNid, UseKeySize; char *cptr, *sptr, *zptr, *CurrentRecordPtr; char CertFingerprint [64], String [512], VariableName [64], VariableValue [256]; $DESCRIPTOR (StringDsc, String); $DESCRIPTOR (VariableNameDsc, VariableName); SESOLA_STRUCT *sesolaptr; SSL *SslPtr; SSL_CIPHER *CipherPtr; SSL_SESSION *SessionPtr; X509 *ClientCertPtr, *ServerCertPtr; ASN1_OBJECT *Asn1Ptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_SESOLA)) WatchThis (WATCHITM(rqptr), WATCH_MOD_SESOLA, "SesolaCgiVariablesApacheModSsl()"); sesolaptr = NULL; if (HTTP2_REQUEST(rqptr)) sesolaptr = (SESOLA_STRUCT*)rqptr->Http2Stream.Http2Ptr->NetIoPtr->SesolaPtr; if (!sesolaptr) sesolaptr = (SESOLA_STRUCT*)rqptr->NetIoPtr->SesolaPtr; SslPtr = sesolaptr->SslPtr; SessionPtr = SSL_get_session (SslPtr); CipherPtr = SSL_get_current_cipher (SslPtr); ServerCertPtr = SSL_get_certificate (SslPtr); if (!SessionPtr || !CipherPtr || !ServerCertPtr) { if (WATCHMOD (rqptr, WATCH_MOD_SESOLA)) WatchThis (WATCHITM(rqptr), WATCH_MOD_SESOLA, "!&X !&X !&X", SessionPtr, CipherPtr, ServerCertPtr); ErrorNoticed (rqptr, SS$_BUGCHECK, ErrorSanityCheck, FI_LI); return (SS$_BUGCHECK); } /***************/ /* basic stuff */ /***************/ if (VMSnok (status = CgiVariable (rqptr, "HTTPS", "true", VarType))) return (status); if (VMSnok (status = CgiVariable (rqptr, "SSL_PROTOCOL", (char*)SSL_get_version(SslPtr), VarType))) return (status); cptr = SSL_SESSION_get_id (SessionPtr, &cnt); zptr = (sptr = String) + sizeof(String)-1; if (cnt) { while (cnt--) { if (sptr >= zptr) break; *sptr++ = HexDigits[(*cptr >> 4) & 0x0f]; if (sptr >= zptr) break; *sptr++ = HexDigits[*cptr++ & 0x0f]; } *sptr = '\0'; if (VMSnok (status = CgiVariable (rqptr, "SSL_SESSION_ID", String, VarType))) return (status); } cptr = (char*)SSL_CIPHER_get_name (CipherPtr); if (VMSnok (status = CgiVariable (rqptr, "SSL_CIPHER", cptr, VarType))) return (status); UseKeySize = SSL_CIPHER_get_bits(CipherPtr, &AlgKeySize); /* same as "mod_SSL" v2.5 */ if (UseKeySize < 56) if (VMSnok (status = CgiVariable (rqptr, "SSL_CIPHER_EXPORT", "true", VarType))) return (status); sys$fao (&NumberFaoDsc, 0, &StringDsc, UseKeySize); if (VMSnok (status = CgiVariable (rqptr, "SSL_CIPHER_USEKEYSIZE", String, VarType))) return (status); sys$fao (&NumberFaoDsc, 0, &StringDsc, AlgKeySize); if (VMSnok (status = CgiVariable (rqptr, "SSL_CIPHER_ALGKEYSIZE", String, VarType))) return (status); if (VMSnok (status = CgiVariable (rqptr, "SSL_VERSION_INTERFACE", APACHE_MOD_SSL_VERSION_INTERFACE, VarType))) return (status); if (VMSnok (status = CgiVariable (rqptr, "SSL_VERSION_LIBRARY", (char*)OpenSSL_version(OPENSSL_VERSION), VarType))) return (status); if (sesolaptr->SNIServerName[0]) if (VMSnok (status = CgiVariable (rqptr, "SSL_TLS_SNI", sesolaptr->SNIServerName, VarType))) return (status); if (sesolaptr->ALPNok) if (VMSnok (status = CgiVariable (rqptr, "SSL_TLS_ALPN", sesolaptr->ALPNok, VarType))) return (status); /****************/ /* client stuff */ /****************/ if (ClientCertPtr = sesolaptr->ClientCertPtr) { sys$fao (&NumberFaoDsc, 0, &StringDsc, X509_get_version(ClientCertPtr)+1); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_M_VERSION", String, VarType))) return (status); i2a_ASN1_INTEGER (SesolaBioMemPtr, X509_get_serialNumber(ClientCertPtr)); BIO_gets (SesolaBioMemPtr, String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_M_SERIAL", String, VarType))) return (status); X509_NAME_oneline (X509_get_subject_name(ClientCertPtr), String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_S_DN", String, VarType))) return (status); sptr = VariableName; for (cptr = "SSL_CLIENT_S_DN_"; *cptr; *sptr++ = *cptr++); for (;;) { cptr = SesolaCertParseDn (String, NULL); if (!cptr) break; if (*cptr == '/') cptr++; zptr = (sptr = VariableName+16) + sizeof(VariableName)-17; while (*cptr && *cptr != '=' && sptr < zptr) *sptr++ = *cptr++; if (!*cptr) break; cptr++; *sptr = '\0'; zptr = (sptr = VariableValue) + sizeof(VariableValue)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (VMSnok (status = CgiVariable (rqptr, VariableName, VariableValue, VarType))) return (status); } X509_NAME_oneline (X509_get_issuer_name(ClientCertPtr), String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_I_DN", String, VarType))) return (status); sptr = VariableName; for (cptr = "SSL_CLIENT_I_DN_"; *cptr; *sptr++ = *cptr++); for (;;) { cptr = SesolaCertParseDn (String, NULL); if (!cptr) break; if (*cptr == '/') cptr++; zptr = (sptr = VariableName+16) + sizeof(VariableName)-17; while (*cptr && *cptr != '=' && sptr < zptr) *sptr++ = *cptr++; if (!*cptr) break; cptr++; *sptr = '\0'; zptr = (sptr = VariableValue) + sizeof(VariableValue)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (VMSnok (status = CgiVariable (rqptr, VariableName, VariableValue, VarType))) return (status); } ASN1_UTCTIME_print (SesolaBioMemPtr, X509_get_notBefore(ClientCertPtr)); BIO_gets (SesolaBioMemPtr, String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_V_START", String, VarType))) return (status); ASN1_UTCTIME_print (SesolaBioMemPtr, X509_get_notAfter(ClientCertPtr)); BIO_gets (SesolaBioMemPtr, String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_V_END", String, VarType))) return (status); #if SESOLA_SINCE_110 X509_ALGOR_get0 (&Asn1Ptr, NULL, NULL, X509_get0_tbs_sigalg(ClientCertPtr)); ObjNid = OBJ_obj2nid (Asn1Ptr); #else ObjNid = OBJ_obj2nid (ClientCertPtr->cert_info->signature->algorithm); #endif if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_A_SIG", ObjNid == NID_undef ? "UNKNOWN" : (char*)OBJ_nid2ln(ObjNid), VarType))) return (status); #if SESOLA_SINCE_110 X509_PUBKEY_get0_param (&Asn1Ptr, NULL, 0, NULL, X509_get_X509_PUBKEY(ClientCertPtr)); ObjNid = OBJ_obj2nid (Asn1Ptr); #else ObjNid = OBJ_obj2nid (ClientCertPtr->cert_info->key->algor->algorithm); #endif if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_A_KEY", ObjNid == NID_undef ? "UNKNOWN" : (char*)OBJ_nid2ln(ObjNid), VarType))) return (status); } #if APACHE_MOD_SSL_SERVER_CERT /* This variable is larger than can be support in a DCL symbol. It can be support in a CGIplus variable stream, but I imagine has a limited range of uses and so is not generated by default. */ if (VarType == CGI_VARIABLE_STREAM) { PEM_write_bio_X509(SesolaBioMemPtr, ClientCertPtr); BIO_read (SesolaBioMemPtr, String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_CERT", String, VarType))) return (status); } #endif /****************/ /* server stuff */ /****************/ if (rqptr->rqPathSet.SSLCGIvar != SESOLA_CGI_VAR_APACHE_MOD_SSL_CLIENT) { sys$fao (&NumberFaoDsc, 0, &StringDsc, X509_get_version(ServerCertPtr)+1); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_M_VERSION", String, VarType))) return (status); i2a_ASN1_INTEGER (SesolaBioMemPtr, X509_get_serialNumber(ServerCertPtr)); BIO_gets (SesolaBioMemPtr, String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_M_SERIAL", String, VarType))) return (status); X509_NAME_oneline (X509_get_subject_name(ServerCertPtr), String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_S_DN", String, VarType))) return (status); sptr = VariableName; for (cptr = "SSL_SERVER_S_DN_"; *cptr; *sptr++ = *cptr++); for (;;) { cptr = SesolaCertParseDn (String, NULL); if (!cptr) break; if (*cptr == '/') cptr++; zptr = (sptr = VariableName+16) + sizeof(VariableName)-17; while (*cptr && *cptr != '=' && sptr < zptr) *sptr++ = *cptr++; if (!*cptr) break; cptr++; *sptr = '\0'; zptr = (sptr = VariableValue) + sizeof(VariableValue)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (VMSnok (status = CgiVariable (rqptr, VariableName, VariableValue, VarType))) return (status); } X509_NAME_oneline (X509_get_issuer_name(ServerCertPtr), String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_I_DN", String, VarType))) return (status); sptr = VariableName; for (cptr = "SSL_SERVER_I_DN_"; *cptr; *sptr++ = *cptr++); for (;;) { cptr = SesolaCertParseDn (String, NULL); if (!cptr) break; if (*cptr == '/') cptr++; zptr = (sptr = VariableName+16) + sizeof(VariableName)-17; while (*cptr && *cptr != '=' && sptr < zptr) *sptr++ = *cptr++; if (!*cptr) break; cptr++; *sptr = '\0'; zptr = (sptr = VariableValue) + sizeof(VariableValue)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (VMSnok (status = CgiVariable (rqptr, VariableName, VariableValue, VarType))) return (status); } ASN1_UTCTIME_print (SesolaBioMemPtr, X509_get_notBefore(ServerCertPtr)); BIO_gets (SesolaBioMemPtr, String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_V_START", String, VarType))) return (status); ASN1_UTCTIME_print (SesolaBioMemPtr, X509_get_notAfter(ServerCertPtr)); BIO_gets (SesolaBioMemPtr, String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_V_END", String, VarType))) return (status); #if SESOLA_SINCE_110 X509_ALGOR_get0 (&Asn1Ptr, NULL, NULL, X509_get0_tbs_sigalg(ServerCertPtr)); ObjNid = OBJ_obj2nid (Asn1Ptr); #else ObjNid = OBJ_obj2nid (ServerCertPtr->cert_info->signature->algorithm); #endif if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_A_SIG", ObjNid == NID_undef ? "UNKNOWN" : (char*)OBJ_nid2ln(ObjNid), VarType))) return (status); #if SESOLA_SINCE_110 X509_PUBKEY_get0_param (&Asn1Ptr, NULL, 0, NULL, X509_get_X509_PUBKEY(ServerCertPtr)); ObjNid = OBJ_obj2nid (Asn1Ptr); #else ObjNid = OBJ_obj2nid (ServerCertPtr->cert_info->key->algor->algorithm); #endif if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_A_KEY", ObjNid == NID_undef ? "UNKNOWN" : (char*)OBJ_nid2ln(ObjNid), VarType))) return (status); #if APACHE_MOD_SSL_SERVER_CERT /* This variable is larger than can be support in a DCL symbol. It can be support in a CGIplus variable stream, but I imagine has a limited range of uses and so is not generated by default. */ if (VarType == CGI_VARIABLE_STREAM) { PEM_write_bio_X509(SesolaBioMemPtr, ServerCertPtr); BIO_read (SesolaBioMemPtr, String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_CERT", String, VarType))) return (status); } #endif } /*******************/ /* X509 extensions */ /*******************/ if (rqptr->rqPathSet.SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL_CLIENT || rqptr->rqPathSet.SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL_EXTENS || rqptr->rqPathSet.SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL_OID) SesolaCgiVariablesExtension (rqptr, VarType); return (SS$_NORMAL); } /*****************************************************************************/ /* Generate some Purveyor style SSL-related CGI variables. */ int SesolaCgiVariablesPurveyor ( REQUEST_STRUCT *rqptr, int VarType ) { static $DESCRIPTOR (NumberFaoDsc, "!UL\0"); int status, KeySize; char String [512]; char *cptr; $DESCRIPTOR (StringDsc, String); SESOLA_STRUCT *sesolaptr; SSL *SslPtr; SSL_CIPHER *CipherPtr; SSL_SESSION *SessionPtr; X509 *ServerCertPtr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_SESOLA)) WatchThis (WATCHITM(rqptr), WATCH_MOD_SESOLA, "SesolaCgiVariablesPurveyor()"); sesolaptr = NULL; if (HTTP2_REQUEST(rqptr)) sesolaptr = (SESOLA_STRUCT*)rqptr->Http2Stream.Http2Ptr->NetIoPtr->SesolaPtr; if (!sesolaptr) sesolaptr = (SESOLA_STRUCT*)rqptr->NetIoPtr->SesolaPtr; SslPtr = sesolaptr->SslPtr; SessionPtr = SSL_get_session (SslPtr); CipherPtr = SSL_get_current_cipher (SslPtr); ServerCertPtr = SSL_get_certificate (SslPtr); if (!SessionPtr || !CipherPtr || !ServerCertPtr) { if (WATCHMOD (rqptr, WATCH_MOD_SESOLA)) WatchThis (WATCHITM(rqptr), WATCH_MOD_SESOLA, "!&X !&X !&X", SessionPtr, CipherPtr, ServerCertPtr); ErrorNoticed (rqptr, SS$_BUGCHECK, ErrorSanityCheck, FI_LI); return (SS$_BUGCHECK); } cptr = (char*)SSL_CIPHER_get_name (CipherPtr); if (VMSnok (status = CgiVariable (rqptr, "SSL_CIPHER", cptr, VarType))) return (status); KeySize = SSL_CIPHER_get_bits (CipherPtr, NULL); sys$fao (&NumberFaoDsc, 0, &StringDsc, KeySize); if (VMSnok (status = CgiVariable (rqptr, "SSL_CIPHER_KEYSIZE", String, VarType))) return (status); if (!sesolaptr->ClientCertPtr) { if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_CA", "NONE", VarType))) return (status); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_DN", "NONE", VarType))) return (status); } else { X509_NAME_oneline (X509_get_issuer_name(sesolaptr->ClientCertPtr), String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_CA", String, VarType))) return (status); X509_NAME_oneline (X509_get_subject_name(sesolaptr->ClientCertPtr), String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_DN", String, VarType))) return (status); } if (rqptr->RemoteUser[0] && rqptr->rqAuth.SourceRealm == AUTH_SOURCE_X509) cptr = "TRUE"; else cptr = "FALSE"; if (VMSnok (status = CgiVariable (rqptr, "SSL_CLIENT_AUTHENTICATED", cptr, VarType))) return (status); if (VMSnok (status = CgiVariable (rqptr, "SECURITY_STATUS", "SSL", VarType))) return (status); X509_NAME_oneline (X509_get_issuer_name(ServerCertPtr), String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_CA", String, VarType))) return (status); X509_NAME_oneline (X509_get_subject_name(ServerCertPtr), String, sizeof(String)); if (VMSnok (status = CgiVariable (rqptr, "SSL_SERVER_DN", String, VarType))) return (status); if (VMSnok (status = CgiVariable (rqptr, "SSL_VERSION", (char*)SSL_get_version(SslPtr), VarType))) return (status); return (SS$_NORMAL); } /*****************************************************************************/ /* Generate X509 extension CGI variables. */ int SesolaCgiVariablesExtension ( REQUEST_STRUCT *rqptr, int VarType ) { /* see also SesolaCertExtensions() */ static char *ShortHand [] = { "X509V3_SUBJECT_ALTERNATIVE_NAME", "X509V3_SAN", "X509V3_SUBJECT_ALTERNATIVE_NAME_USERPRINCIPALNAME", "X509V3_SAN_UPN", "X509V3_SUBJECT_ALTERNATIVE_NAME_RFC822NAME", "X509V3_SAN_822", NULL }; int cnt, idx, status; char *aptr, *cptr, *sptr, *zptr; char NameValue [256+2048]; SESOLA_STRUCT *sesolaptr; SSL *SslPtr; X509 *CertPtr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_SESOLA)) WatchThis (WATCHITM(rqptr), WATCH_MOD_SESOLA, "SesolaCgiVariablesExtension()"); sesolaptr = NULL; if (HTTP2_REQUEST(rqptr)) sesolaptr = (SESOLA_STRUCT*)rqptr->Http2Stream.Http2Ptr->NetIoPtr->SesolaPtr; if (!sesolaptr) sesolaptr = (SESOLA_STRUCT*)rqptr->NetIoPtr->SesolaPtr; if (rqptr->rqPathSet.SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL_CLIENT) cnt = 1; else cnt = 2; for (; cnt; cnt--) { sptr = NameValue; if (cnt == 2) { /* server certificate extensions */ SslPtr = sesolaptr->SslPtr; CertPtr = SSL_get_certificate (SslPtr); for (cptr = "SSL_SERVER_E_"; *cptr; *sptr++ = *cptr++); } else { /* client certificate extensions */ if (!(CertPtr = sesolaptr->ClientCertPtr)) break; for (cptr = "SSL_CLIENT_E_"; *cptr; *sptr++ = *cptr++); } if (rqptr->rqPathSet.SSLCGIvar == SESOLA_CGI_VAR_APACHE_MOD_SSL_OID) SesolaCertExtension (CertPtr, "OID"); else SesolaCertExtension (CertPtr, NULL); while (cptr = SesolaCertExtension (NULL, NULL)) { zptr = (sptr = NameValue+13) + sizeof(NameValue)-14; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (VMSnok (status = CgiVariable (rqptr, NameValue, NULL, VarType))) return (status); } for (idx = 0; ShortHand[idx]; idx += 2) { if (cptr = SesolaCertExtension (NULL, ShortHand[idx])) { while (*cptr && *cptr != '=') cptr++; zptr = (sptr = NameValue+13) + sizeof(NameValue)-14; for (aptr = ShortHand[idx+1]; *aptr && sptr < zptr; *sptr++ = *aptr++); while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; if (VMSnok (status = CgiVariable (rqptr, NameValue, NULL, VarType))) return (status); } } } return (SS$_NORMAL); } /*****************************************************************************/ /* For compilations without SSL these functions provide LINKage stubs for the rest of the HTTPd modules, allowing for just recompiling the Sesola module to integrate the SSL functionality. */ /*********************/ #else /* not SESOLA */ /*********************/ /* external storage */ extern WATCH_STRUCT Watch; SesolaCgiGenerateVariables ( REQUEST_STRUCT *rqptr, int VarType ) { int status; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_SESOLA)) WatchThis (WATCHITM(rqptr), WATCH_MOD_SESOLA, "SesolaCgiGenerateVariables()"); if (VMSnok (status = CgiVariable (rqptr, "SECURITY_STATUS", "NONE", VarType))) return (status); return (SS$_NORMAL); } /************************/ #endif /* ifdef SESOLA */ /************************/ /*****************************************************************************/