int handle_startup(int which, void * obj) { struct nebstruct_process_struct *ps = (struct nebstruct_process_struct *)obj; time_t now = ps->timestamp.tv_sec; switch(ps->type) { case NEBTYPE_PROCESS_START: if(daemon_mode && !sigrestart) return 0; case NEBTYPE_PROCESS_DAEMONIZE: { json_t * pubdef = NULL, *pulldef = NULL, *reqdef = NULL; int numthreads = 1; if(get_values(config, "iothreads", JSON_INTEGER, 0, &numthreads, "publish", JSON_OBJECT, 0, &pubdef, "pull", JSON_OBJECT, 0, &pulldef, "reply", JSON_OBJECT, 0, &reqdef, NULL) != 0) { syslog(LOG_ERR, "Parameter error while starting NagMQ"); return -1; } if(!pubdef && !pulldef && !reqdef) return 0; zmq_ctx = zmq_init(numthreads); if(zmq_ctx == NULL) { syslog(LOG_ERR, "Error initialzing ZMQ: %s", zmq_strerror(errno)); return -1; } if(pubdef && handle_pubstartup(pubdef) < 0) return -1; if(pulldef) { unsigned long interval = 2; get_values(pulldef, "interval", JSON_INTEGER, 0, &interval, NULL); if((pullsock = getsock("pull", ZMQ_PULL, pulldef)) == NULL) return -1; schedule_new_event(EVENT_USER_FUNCTION, 1, now, 1, interval, NULL, 1, input_reaper, pullsock, 0); } if(reqdef) { unsigned long interval = 2; get_values(reqdef, "interval", JSON_INTEGER, 0, &interval, NULL); if((reqsock = getsock("reply", ZMQ_REP, reqdef)) == NULL) return -1; schedule_new_event(EVENT_USER_FUNCTION, 1, now, 1, interval, NULL, 1, input_reaper, reqsock, 0); } if(pulldef || reqdef) neb_register_callback(NEBCALLBACK_TIMED_EVENT_DATA, handle, 0, handle_timedevent); break; } case NEBTYPE_PROCESS_SHUTDOWN: case NEBTYPE_PROCESS_RESTART: if(pullsock) zmq_close(pullsock); if(reqsock) zmq_close(reqsock); if(pubext) zmq_close(pubext); zmq_term(zmq_ctx); break; case NEBTYPE_PROCESS_EVENTLOOPSTART: case NEBTYPE_PROCESS_EVENTLOOPEND: if(pubext) { struct payload * payload; payload = payload_new(); switch(ps->type) { case NEBTYPE_PROCESS_EVENTLOOPSTART: payload_new_string(payload, "type", "eventloopstart"); break; case NEBTYPE_PROCESS_EVENTLOOPEND: payload_new_string(payload, "type", "eventloopend"); break; } payload_new_timestamp(payload, "timestamp", &ps->timestamp); payload_finalize(payload); process_payload(payload); } break; } return 0; }
int main(int argc, char *argv[]) { int c, poll = 0, reqversion = 0, rc = -1; char *cacertfile = NULL, *keyfile = NULL, *challenge = NULL, *savedrequestfile = NULL, *requestfile = NULL, *dn = NULL, *spkacfile = NULL, *endrequest = NULL; scep_t scep; BIO *repbio; char *url = "http://localhost/cgi-bin"; scepmsg_t *msg; unsigned char *checkNonce = NULL; /* initialize what you can */ scepinit(); scep_clear(&scep); /* we are a client */ scep.client = 1; /* parse command line */ while (EOF != (c = getopt(argc, argv, "dc:e:r:s:k:w:pu:2a:q:"))) switch (c) { case 'd': debug++; break; case 'e': endrequest = optarg; break; case 'c': cacertfile = optarg; break; case 's': savedrequestfile = optarg; case 'r': /* the request file will also contain the self */ /* signed certificate */ requestfile = optarg; break; case 'k': keyfile = optarg; break; case 'w': challenge = optarg; break; case 'p': poll = 1; break; case 'q': scep.community = optarg; break; case 'u': url = optarg; break; case '2': reqversion = 1; break; case 'a': spkacfile = optarg; break; } /* stop immediately if request or key is missing */ /* (even in the case of a version 2 proxied request, we need */ /* a request as the carrier of the proxy entities public key) */ if (keyfile == NULL) { BIO_printf(bio_err, "%s:%d: key file is required argument\n", __FILE__, __LINE__); goto err; } if (requestfile == NULL) { BIO_printf(bio_err, "%s:%d: request file is required " "argument\n", __FILE__, __LINE__); goto err; } /* we are preparing the request message */ msg = &scep.request; /* decode the URL */ if (parseurl(&scep, url) < 0) { BIO_printf(bio_err, "%s:%d: cannot parse url\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: decoded URL %s|%d|%s\n", __FILE__, __LINE__, scep.h.httphost, scep.h.httpport, scep.h.httppath); /* read the client key and request information */ if (read_clientstuff(&scep, requestfile, keyfile) < 0) { BIO_printf(bio_err, "%s:%d: failed to read client stuff\n", __FILE__, __LINE__); goto err; } /* now we have to decide about the payload we want to have */ /* with our scep request: */ /* - for a version 1 request, this will always be the original */ /* certificate signing request */ /* - for a version 2 request, it will be a payload structure */ switch (reqversion) { case 0: /* for a version 1 client, client pubkey and client req */ /* coincide */ scep.requestorpubkey = scep.clientpubkey; scep.requestorreq = scep.clientreq; if (debug) BIO_printf(bio_err, "%s:%d: end request coincides " "with SCEP client\n", __FILE__, __LINE__); break; case 1: msg->rd.payload = payload_new(); rc = -1; if (spkacfile) { if (debug) BIO_printf(bio_err, "%s:%d: reading spki " "from %s\n", __FILE__, __LINE__, spkacfile); rc = read_requestorstuff(&scep, 1, spkacfile); } else if (endrequest) { if (debug) BIO_printf(bio_err, "%s:%d: reading X509 req " "from %s\n", __FILE__, __LINE__, endrequest); rc = read_requestorstuff(&scep, 0, endrequest); } if (rc < 0) { BIO_printf(bio_err, "%s:%d: could not read end " "request data\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: end request read\n", __FILE__, __LINE__); break; } /* set the transaction id value */ scep.transId = key_fingerprint(scep.requestorpubkey); if (debug) BIO_printf(bio_err, "%s:%d: transaction ID is %s\n", __FILE__, __LINE__, scep.transId); /* read the CA certificate file */ if (read_castuff(&scep, cacertfile) < 0) { BIO_printf(bio_err, "%s:%d: read CA certificate info\n", __FILE__, __LINE__); } if (debug) BIO_printf(bio_err, "%s:%d: CA certificate read\n", __FILE__, __LINE__); /* for SPKI requests, there should be exactly one more argument */ /* namely the distinguished name */ if (spkacfile) { if ((argc - optind) != 1) { BIO_printf(bio_err, "%s:%d: DN argument needed\n", __FILE__, __LINE__); goto err; } dn = argv[optind]; if (debug) BIO_printf(bio_err, "%s:%d: DN argument is '%s'\n", __FILE__, __LINE__, dn); /* convert the DN into attributes and add them to the */ /* payload */ if (payload_dn_to_attrs(msg->rd.payload, dn) < 0) { BIO_printf(bio_err, "%s:%d: failed to add DN attrs\n", __FILE__, __LINE__); goto err; } } /* skip creation of a request message when polling */ if (poll) goto pollinginit; /* pack the request as a PKSCReq message, of type PKCSReq */ switch (reqversion) { case 0: msg->messageType = SCEP_MESSAGE_TYPE_PKCSREQ; msg->rd.req = scep.clientreq; break; case 1: /* build a version 2 payload */ if (debug) BIO_printf(bio_err, "%s:%d: building version 2 " "payload\n", __FILE__, __LINE__); if (scep.requestorreq) payload_set_req(msg->rd.payload, scep.requestorreq); if (scep.requestorspki) payload_set_spki(msg->rd.payload, scep.requestorspki); /* set the correct message type */ if (scep.community) { /* compute the authenticator from the original */ /* request and the community */ msg->messageType = SCEP_MESSAGE_TYPE_V2PROXY; } else { msg->messageType = SCEP_MESSAGE_TYPE_V2REQUEST; } break; } /* write the request to the request file, for later perusal */ if (savedrequestfile) { BIO *reqbio; reqbio = BIO_new(BIO_s_file()); BIO_write_filename(reqbio, savedrequestfile); switch (reqversion) { case 0: /* version 1 request has a X509_REQ payload */ PEM_write_bio_X509_REQ(reqbio, msg->rd.req); break; case 1: /* version 2 requests have a "real" payload */ i2d_payload_bio(reqbio, msg->rd.payload); break; } BIO_free(reqbio); } goto common; pollinginit: /* when polling, the request is a GetCertInitial message */ msg->messageType = SCEP_MESSAGE_TYPE_GETCERTINITIAL; /* the contents is the pair issuer and subject */ msg->rd.is = (issuer_and_subject_t *)malloc( sizeof(issuer_and_subject_t)); msg->rd.is->issuer = X509_get_subject_name(scep.cacert); msg->rd.is->subject = NULL; /* when polling we should read the request from request file */ /* (only needed for the distinguished name of the client) */ if (debug) BIO_printf(bio_err, "%s:%d: getting subject X509_NAME\n", __FILE__, __LINE__); switch (reqversion) { case 0: msg->rd.is->subject = X509_REQ_get_subject_name(scep.clientreq); break; case 1: if (scep.requestorreq) msg->rd.is->subject = X509_REQ_get_subject_name(scep.requestorreq); if (scep.requestorspki) { if (debug) BIO_printf(bio_err, "%s:%d: converting DN '%s' " "to X509_NAME\n", __FILE__, __LINE__, dn); msg->rd.is->subject = ldap_to_x509(dn); } break; } if (msg->rd.is->subject == NULL) { BIO_printf(bio_err, "%s:%d: no subject found\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: issuer and subject found\n", __FILE__, __LINE__); common: /* create a self signed certificate for use with SCEP */ if (selfsigned(&scep) < 0) { BIO_printf(bio_err, "%s:%d: failed to create self signed " "certificate\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: self signed certificate created\n", __FILE__, __LINE__); /* set the senderNonce */ scep.senderNonceLength = 16; scep.senderNonce = (unsigned char *)malloc(scep.senderNonceLength); RAND_bytes(scep.senderNonce, scep.senderNonceLength); if (debug) BIO_printf(bio_err, "%s:%d: senderNonce set\n", __FILE__, __LINE__); checkNonce = scep.senderNonce; /* all messages sent from the client are base 64 encoded */ msg->base64 = 1; /* encode */ if (encode(&scep) < 0) { BIO_printf(bio_err, "%s:%d: encoding the request failed\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: encoded bytes: %d\n", __FILE__, __LINE__, scep.request.length); /* send the request to the server, read the reply */ repbio = getrequest(&scep); if (repbio == NULL) { BIO_printf(bio_err, "%s:%d: failed to read correct reply\n", __FILE__, __LINE__); goto err; } /* analyze the reply */ if (decode(&scep, repbio) < 0) { BIO_printf(bio_err, "%s:%d: decoding the reply failed\n", __FILE__, __LINE__); goto err; } /* display some information about the reply */ printf("transaction id: %s\n", scep.transId); printf("PKIstatus: %s\n", (scep.reply.pkiStatus) ? scep.reply.pkiStatus : "(null)"); printf("reply message type: %s\n", scep.reply.messageType); if (scep.reply.failinfo) { printf("failinfo: %s\n", scep.reply.failinfo); } /* make sure we get a CertRep message back */ if (strcmp(scep.reply.messageType, SCEP_MESSAGE_TYPE_CERTREP)) { BIO_printf(bio_err, "%s:%d: only CertRep message acceptable " " in response to PKCSReq/GetCertInitial\n", __FILE__, __LINE__); goto err; } /* check for the Nonces */ if (memcmp(checkNonce, scep.recipientNonce, 16)) { BIO_printf(bio_err, "%s:%d: recipientNonce != sent " "senderNonce\n", __FILE__, __LINE__); goto err; } if (debug) BIO_printf(bio_err, "%s:%d: Nonce check OK\n", __FILE__, __LINE__); if (scep.reply.pkiStatus == NULL) { BIO_printf(bio_err, "no pkiStatus returned\n"); exit(1); } switch (atoi(scep.reply.pkiStatus)) { case PKI_SUCCESS: /* Success */ scep.clientcert = extract_cert(&scep); if (debug) BIO_printf(bio_err, "%s:%d: certificate returned %p\n", __FILE__, __LINE__, scep.clientcert); if (scep.clientcert) { BIO *cb; cb = BIO_new(BIO_s_file()); BIO_set_fp(cb, stdout, BIO_NOCLOSE); PEM_write_bio_X509(cb, scep.clientcert); BIO_free(cb); } exit(EXIT_SUCCESS); break; case PKI_FAILURE: /* Failure */ if (debug) BIO_printf(bio_err, "%s:%d: request failed: %s\n", __FILE__, __LINE__, scep.reply.failinfo); exit(1); break; case PKI_PENDING: /* Pending */ if (debug) BIO_printf(bio_err, "%s:%d: request still pending\n", __FILE__, __LINE__); exit(2); break; } /* error return */ err: ERR_print_errors(bio_err); exit(EXIT_FAILURE); }
PAYLOAD payload_new_reply(void) { return(payload_new(NULL, 0)); }