00001
00002
00003 const char *XrdCryptosslX509ReqCVSID = "$Id: XrdCryptosslX509Req.cc 31508 2009-12-02 19:11:01Z brun $";
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <unistd.h>
00021 #include <errno.h>
00022
00023 #include <XrdCrypto/XrdCryptosslRSA.hh>
00024 #include <XrdCrypto/XrdCryptosslX509Req.hh>
00025 #include <XrdCrypto/XrdCryptosslAux.hh>
00026 #include <XrdCrypto/XrdCryptosslTrace.hh>
00027
00028 #include <openssl/pem.h>
00029
00030
00031 XrdCryptosslX509Req::XrdCryptosslX509Req(XrdSutBucket *buck) : XrdCryptoX509Req()
00032 {
00033
00034 EPNAME("X509Req::XrdCryptosslX509Req_bio");
00035
00036
00037 creq = 0;
00038 subject = "";
00039 subjecthash = "";
00040 bucket = 0;
00041 pki = 0;
00042
00043
00044 if (!buck) {
00045 DEBUG("got undefined opaque buffer");
00046 return;
00047 }
00048
00049
00050
00051 BIO *bmem = BIO_new(BIO_s_mem());
00052 if (!bmem) {
00053 DEBUG("unable to create BIO for memory operations");
00054 return;
00055 }
00056
00057
00058 int nw = BIO_write(bmem,(const void *)(buck->buffer),buck->size);
00059 if (nw != buck->size) {
00060 DEBUG("problems writing data to memory BIO (nw: "<<nw<<")");
00061 return;
00062 }
00063
00064
00065 if (!PEM_read_bio_X509_REQ(bmem,&creq,0,0)) {
00066 DEBUG("unable to read certificate request to memory BIO");
00067 return;
00068 }
00069
00070
00071 BIO_free(bmem);
00072
00073
00074 Subject();
00075
00076
00077 EVP_PKEY *evpp = X509_REQ_get_pubkey(creq);
00078
00079 if (evpp) {
00080
00081 if (!pki)
00082 pki = new XrdCryptosslRSA(evpp, 0);
00083 } else {
00084 DEBUG("could not access the public key");
00085 }
00086 }
00087
00088
00089 XrdCryptosslX509Req::XrdCryptosslX509Req(X509_REQ *xc) : XrdCryptoX509Req()
00090 {
00091
00092 EPNAME("X509Req::XrdCryptosslX509Req_x509");
00093
00094
00095 creq = 0;
00096 subject = "";
00097 subjecthash = "";
00098 bucket = 0;
00099 pki = 0;
00100
00101
00102 if (!xc) {
00103 DEBUG("got undefined X509 object");
00104 return;
00105 }
00106
00107
00108 creq = xc;
00109
00110
00111 Subject();
00112
00113
00114 EVP_PKEY *evpp = X509_REQ_get_pubkey(creq);
00115
00116 if (evpp) {
00117
00118 if (!pki)
00119 pki = new XrdCryptosslRSA(evpp, 0);
00120 } else {
00121 DEBUG("could not access the public key");
00122 }
00123 }
00124
00125
00126 XrdCryptosslX509Req::~XrdCryptosslX509Req()
00127 {
00128
00129
00130
00131 if (creq) X509_REQ_free(creq);
00132
00133 if (pki) delete pki;
00134 }
00135
00136
00137 const char *XrdCryptosslX509Req::Subject()
00138 {
00139
00140 EPNAME("X509Req::Subject");
00141
00142
00143 if (subject.length() <= 0) {
00144
00145
00146 if (!creq) {
00147 DEBUG("WARNING: no certificate available - cannot extract subject name");
00148 return (const char *)0;
00149 }
00150
00151
00152 subject = X509_NAME_oneline(X509_REQ_get_subject_name(creq), 0, 0);
00153 }
00154
00155
00156 return (subject.length() > 0) ? subject.c_str() : (const char *)0;
00157 }
00158
00159
00160 const char *XrdCryptosslX509Req::SubjectHash()
00161 {
00162
00163 EPNAME("X509Req::SubjectHash");
00164
00165
00166 if (subjecthash.length() <= 0) {
00167
00168
00169 if (creq) {
00170 char chash[15];
00171 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00172 sprintf(chash,"%08lx.0",X509_NAME_hash_old(creq->req_info->subject));
00173 #else
00174 sprintf(chash,"%08lx.0",X509_NAME_hash(creq->req_info->subject));
00175 #endif
00176 subjecthash = chash;
00177 } else {
00178 DEBUG("WARNING: no certificate available - cannot extract subject hash");
00179 }
00180 }
00181
00182
00183 return (subjecthash.length() > 0) ? subjecthash.c_str() : (const char *)0;
00184 }
00185
00186
00187 XrdCryptoX509Reqdata XrdCryptosslX509Req::GetExtension(const char *oid)
00188 {
00189
00190 EPNAME("X509Req::GetExtension");
00191 XrdCryptoX509Reqdata ext = 0;
00192
00193
00194 if (!oid) {
00195 DEBUG("OID string not defined");
00196 return ext;
00197 }
00198
00199
00200 if (!creq) {
00201 DEBUG("certificate is not initialized");
00202 return ext;
00203 }
00204
00205
00206 STACK_OF(X509_EXTENSION) *esk = X509_REQ_get_extensions(creq);
00207
00208 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00209 int numext = sk_X509_EXTENSION_num(esk);
00210 #else
00211 int numext = sk_num(esk);
00212 #endif
00213 if (numext <= 0) {
00214 DEBUG("certificate has got no extensions");
00215 return ext;
00216 }
00217 DEBUG("certificate request has "<<numext<<" extensions");
00218
00219
00220
00221 int nid = OBJ_sn2nid(oid);
00222 bool usenid = (nid > 0);
00223
00224
00225 int i = 0;
00226 X509_EXTENSION *wext = 0;
00227 for (i = 0; i< numext; i++) {
00228 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00229 wext = sk_X509_EXTENSION_value(esk, i);
00230 #else
00231 wext = (X509_EXTENSION *)sk_value(esk, i);
00232 #endif
00233 if (usenid) {
00234 int enid = OBJ_obj2nid(X509_EXTENSION_get_object(wext));
00235 if (enid == nid)
00236 break;
00237 } else {
00238
00239 char s[256];
00240 OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(wext), 1);
00241 if (!strcmp(s, oid))
00242 break;
00243 }
00244 wext = 0;
00245 }
00246
00247
00248 if (!wext) {
00249 DEBUG("Extension "<<oid<<" not found");
00250 return ext;
00251 }
00252
00253
00254 return (XrdCryptoX509Reqdata)wext;
00255 }
00256
00257
00258 XrdSutBucket *XrdCryptosslX509Req::Export()
00259 {
00260
00261 EPNAME("X509Req::Export");
00262
00263
00264 if (bucket) {
00265 DEBUG("serialization already performed:"
00266 " return previous result ("<<bucket->size<<" bytes)");
00267 return bucket;
00268 }
00269
00270
00271 if (!creq) {
00272 DEBUG("certificate is not initialized");
00273 return 0;
00274 }
00275
00276
00277
00278 BIO *bmem = BIO_new(BIO_s_mem());
00279 if (!bmem) {
00280 DEBUG("unable to create BIO for memory operations");
00281 return 0;
00282 }
00283
00284
00285 if (!PEM_write_bio_X509_REQ(bmem, creq)) {
00286 DEBUG("unable to write certificate request to memory BIO");
00287 return 0;
00288 }
00289
00290
00291 char *bdata = 0;
00292 int blen = BIO_get_mem_data(bmem, &bdata);
00293 DEBUG("BIO data: "<<blen<<" bytes at 0x"<<(int *)bdata);
00294
00295
00296 bucket = new XrdSutBucket(0,0,kXRS_x509_req);
00297 if (bucket) {
00298
00299 bucket->SetBuf(bdata, blen);
00300 DEBUG("result of serialization: "<<bucket->size<<" bytes");
00301 } else {
00302 DEBUG("unable to create bucket for serialized format");
00303 BIO_free(bmem);
00304 return 0;
00305 }
00306
00307
00308 BIO_free(bmem);
00309
00310
00311 return bucket;
00312 }
00313
00314
00315 bool XrdCryptosslX509Req::Verify()
00316 {
00317
00318 EPNAME("X509Req::Verify");
00319
00320
00321 if (!creq)
00322 return 0;
00323
00324
00325 int rc = X509_REQ_verify(creq,X509_REQ_get_pubkey(creq));
00326 if (rc <= 0) {
00327
00328 if (rc == 0) {
00329
00330 DEBUG("signature not OK");
00331 } else {
00332
00333 DEBUG("could not verify signature");
00334 }
00335 return 0;
00336 }
00337
00338 return 1;
00339 }