/*############################################################################## Copyright (C) 2011 HPCC Systems. All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . ############################################################################## */ #include "jliball.hpp" #include "securesocket.hpp" #ifdef _WIN32 #include #else #include #endif char *myfgets(char *s, int size, FILE *stream) { int len = strlen(fgets(s, size, stream)); if(len > 0) s[len - 1] = '\0'; return s; } void inputpassword(const char* prompt, StringBuffer& passwd) { passwd.clear(); #ifdef _WIN32 printf("%s", prompt); char input=0; short num_entries=0; while (0x0d != (input = (char)getch())) { if (input == '\b') { printf("\b \b"); if (num_entries) { num_entries--; } continue; } passwd.append(input); num_entries++; printf("*"); } #else const char* pass = getpass(prompt); passwd.append(pass); #endif } void getpassword(const char* prompt, StringBuffer& passwd) { passwd.clear(); StringBuffer passwd1, passwd2; int tries = 0; while(1) { if(tries++ >= 3) { exit(-1); } inputpassword(prompt, passwd1); inputpassword("\nVerifying password, retype: ", passwd2); if(passwd1.length() < 4) { printf("\npassword too short, should be 4 chars or longer\n"); } else if(strcmp(passwd1.str(), passwd2.str()) != 0) { printf("\npasswords don't match.\n"); } else break; } passwd.append(passwd1.str()); } void usage() { // For now this tool only generates x509 certificates. // New functions can be added. printf("usage: myssl [-crt|-csr|-sign] [options]\n"); printf("-crt: create self-signed certificate and privatekey pair\n"); printf("-csr: create certificate signing request, using an existing privatekey or generating a new privatekey\n"); printf("-sign: sign a CSR with your own certificate/privatekey pair\n"); printf("options:\n"); printf(" -b : batchmode\n"); printf(" -c \n"); printf(" -s \n"); printf(" -l \n"); printf(" -org \n"); printf(" -ou \n"); printf(" -cn \n"); printf(" -days \n"); printf(" -ip \n"); printf(" -ic \n"); printf(" -ir \n"); printf(" -op \n"); printf(" -oc \n"); printf(" -or \n"); printf(" -p \n"); } enum MysslAction { CRT=0, CSR=1, SIGN=2 }; int main(int argc, char* argv[]) { InitModuleObjects(); StringBuffer passwd; if(argc < 2) { usage(); return -1; } else if (stricmp(argv[1], "-?") == 0 || stricmp(argv[1], "-h") == 0 || stricmp(argv[1], "-help") == 0) { usage(); return 0; } bool isBatchMode = false; MysslAction action = CRT; StringBuffer opfname, ocfname, orfname, cbuf, sbuf, lbuf, orgbuf, oubuf, cnbuf, ebuf, daysbuf, pfbuf, cfbuf, rfbuf, pbuf; int i; for (i=1; i 0) daysbuf.append(buf); printf("Private Key file(leave it blank if you want to generate a private key): "); myfgets(buf,128,stdin); pfbuf.append(buf); getpassword("Enter PEM pass phrase: ", pbuf); } else if(action == CSR) { printf("Private Key file(leave it blank if you want to generate a private key): "); myfgets(buf,128,stdin); pfbuf.append(buf); getpassword("Enter PEM pass phrase: ", pbuf); } } else if(action == SIGN) { printf("csr file: "); myfgets(buf,128,stdin); rfbuf.append(buf); printf("CA certificate file: "); myfgets(buf,128,stdin); cfbuf.append(buf); printf("CA privatekey file: "); myfgets(buf,128,stdin); pfbuf.append(buf); getpassword("CA private key passphrase: ", pbuf); printf("\nNumber of days for the certificate to be valid: "); myfgets(buf,128,stdin); daysbuf.append(buf); } } try { Owned opf; Owned opfio; if(opfname.length() > 0) { opf.setown(createIFile(opfname.str())); opfio.setown(opf->open(IFOcreate)); } Owned ocf; Owned ocfio; if(ocfname.length() > 0) { ocf.setown(createIFile(ocfname.str())); ocfio.setown(ocf->open(IFOcreate)); } Owned orf; Owned orfio; if(orfname.length() > 0) { orf.setown(createIFile(orfname.str())); orfio.setown(orf->open(IFOcreate)); } if(action == CRT || action == CSR) { Owned cc = createCertificate(); if(cbuf.length() > 0) cc->setCountry(cbuf.str()); if(sbuf.length() > 0) cc->setState(sbuf.str()); if(lbuf.length() > 0) cc->setCity(lbuf.str()); if(orgbuf.length() > 0) cc->setOrganization(orgbuf.str()); if(oubuf.length() > 0) cc->setOrganizationalUnit(oubuf.str()); if(ebuf.length() > 0) cc->setEmail(ebuf.str()); if(cnbuf.length() > 0) cc->setDestAddr(cnbuf.str()); if(action == CSR) { if(pbuf.length() > 0) cc->setPassphrase(pbuf.str()); else throw MakeStringException(-1, "passphrase not specified."); StringBuffer csrbuf, privkey; if(pfbuf.length() == 0) { cc->generateCSR(privkey, csrbuf); if(opfio.get() != NULL) opfio->write(0, privkey.length(), privkey.str()); else printf("\n%s\n", privkey.str()); if(orfio.get() != NULL) orfio->write(0, csrbuf.length(), csrbuf.str()); else printf("\n%s\n", csrbuf.str()); } else { privkey.loadFile(pfbuf.str()); cc->generateCSR(privkey.str(), csrbuf); if(orfio.get() != NULL) orfio->write(0, csrbuf.length(), csrbuf.str()); else printf("\n%s\n", csrbuf.str()); } } else if(action == CRT) { if(daysbuf.length() > 0) { cc->setDays(atoi(daysbuf.str())); } if(pbuf.length() > 0) cc->setPassphrase(pbuf.str()); else throw MakeStringException(-1, "passphrase not specified."); StringBuffer certbuf, privkey; if(pfbuf.length() == 0) { cc->generate(certbuf, privkey); if(opfio.get() != NULL) opfio->write(0, privkey.length(), privkey.str()); else printf("\n%s\n", privkey.str()); if(ocfio.get() != NULL) ocfio->write(0, certbuf.length(), certbuf.str()); else printf("\n%s\n", certbuf.str()); } else { privkey.loadFile(pfbuf.str()); cc->generate(certbuf, privkey.str()); if(ocfio.get() != NULL) ocfio->write(0, certbuf.length(), certbuf.str()); else printf("\n%s\n\n", certbuf.str()); } } } else if(stricmp(argv[1], "-sign") == 0) { StringBuffer csrbuf, ca_cert, ca_privkey, certbuf; if(rfbuf.length() == 0 || cfbuf.length() == 0 || pfbuf.length() == 0) throw MakeStringException(-1, "You need to specify csr file, certificate file and privatekey file"); csrbuf.loadFile(rfbuf.str()); ca_cert.loadFile(cfbuf.str()); ca_privkey.loadFile(pfbuf.str()); if(pbuf.length() == 0) throw MakeStringException(-1, "passphrase not specified."); int days = 365; if(daysbuf.length() > 0) { days = atoi(daysbuf.str()); } signCertificate(csrbuf.str(),ca_cert.str(), ca_privkey.str(), pbuf.str(), days, certbuf); if(ocfio.get() != NULL) ocfio->write(0, certbuf.length(), certbuf.str()); else printf("\n%s\n", certbuf.str()); } else { usage(); return -1; } } catch(IException* e) { StringBuffer errmsg; printf("\nError - %s\n", e->errorMessage(errmsg).str()); e->Release(); } catch(...) { printf("\nUnknown error."); } releaseAtoms(); return 0; }