SECKEYPrivateKey* PrivateKeyFromPrivateKeyTemplate(SECItem* aObjID, CK_ATTRIBUTE* aTemplate, CK_ULONG aTemplateSize) { // Create a generic object with the contents of the key ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot.get()) { return nullptr; } ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot.get(), aTemplate, aTemplateSize, PR_FALSE)); if (!obj.get()) { return nullptr; } // Have NSS translate the object to a private key by inspection // and make a copy we can own ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), aObjID, nullptr)); if (!privKey.get()) { return nullptr; } return SECKEY_CopyPrivateKey(privKey.get()); }
void UserProcessingCenter::handleKerberosLogin(CMazeMsg* context) { //cout<<":: kerberos login:: "<<endl; debug("kerberos login request"); char *pbuf = context->getMsg(); int rt = context->getLen(); MBlockSocket *pclient = context->getSocket(); UserDatabase *userdb = UserDatabase::getInstance(); KMsgHead kmsghead; if(kmsghead.unserialize(pbuf,rt)!=-1) { switch(kmsghead.msgtype) { case USER_LOGIN_REQUEST: { //cout<<"::kerberos login::"<<endl; UserLoginRequest req; if(req.unserialize(pbuf,rt)!=-1) { USERDB *userinfo = new USERDB; //debug("recv req from user %d to @time %d"<<req.uid<<" "<<req.ts); bool logfind=false; if(req.uid!=0) { debug("recv req from user id to @time--->"<<req.uid<<" "<<req.ts); logfind=(userdb->get_record( req.uid,userinfo) == 0); debug("find user %d 's user info"<<req.uid); } else { debug("recv req from user email to @time---->"<<req.emailAddr<<" "<<req.ts); string emailAddr=req.emailAddr; string badEmail = string("*****@*****.**"); if(emailAddr == badEmail) { cout<<"--------bad email--------"<<endl; logfind = false; } else { logfind=(userdb->get_record(emailAddr,userinfo) == 0); debug("find user %s 's user info"<<emailAddr.c_str()); } } if(logfind) { //generate ticket and send it back to User here... UserLoginReply reply; strncpy(reply.userInfo.NickName,userinfo->NickName,24); strncpy(reply.userInfo.MailAddr,userinfo->MailAddr,128); reply.userInfo.UID=userinfo->UID; reply.userInfo.IP=pclient->GetPeerName().GetIP(); //TODO reply.userInfo.ServerPort=pclient->GetPeerName().GetPort(); //TODO reply.userInfo.Account=userinfo->Account; reply.userInfo.Level=userinfo->Level; reply.userInfo.LastAccountAddTime=(unsigned)userinfo->LastAddAccount; //get user password(key) from user database; string userKey=userinfo->Pwd; //get tgs key from config or database. string tgsKey ="tgskey"; //generate a random string to be the session key shared by user and tgs. string sessionKey=GenRandomKey(); unsigned ts=(unsigned)time(NULL);//the time-stamp of the ticket release. reply.ts =ts; reply.life =TGS_TICKET_LIFE;//the life of the ticket below reply.privilege=0;//TODO privilege of user.. reply.head.src=0; reply.head.dst=req.uid; reply.head.status=0; reply.sessionKey.set(sessionKey.c_str(),sessionKey.length()); Ticket ticket; ticket.uid=req.uid; ticket.uaddr=0; //TODO ticket.ts=ts; ticket.life=TGS_TICKET_LIFE; ticket.privilege=0;//TODO; ticket.sessionKey.set(sessionKey.c_str(),sessionKey.length()); reply.cipheredTicket=ticket.serializeAndEncrypt(tgsKey.c_str(),tgsKey.length()); RawData result=reply.serializeAndEncrypt(userKey.c_str(),userKey.length()); debug("AS:\tGrant ticket and session key {%s} to user %d\n"<<sessionKey.c_str()<<req.uid); unsigned int ip = pclient->GetPeerName().GetIP(); string ip_str=pclient->GetPeerName().ip(); pclient->SendPacket(result.data,result.len); char buf[256]; time_t timep=time(NULL); struct tm *p=localtime(&timep); sprintf(buf,"%d_%0.2d_%0.2d_login.txt",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday); Configuration config = Configuration::getInstance(); string logDir = config.get("log"); string logName = logDir + buf; ofstream loginLogOutput(logName.c_str(),ofstream::app); sprintf(buf,"%.2d:%.2d:%.2d %10d %15s kerbroslogin ",p->tm_hour,p->tm_min,p->tm_sec,userinfo->UID,ip_str.c_str()); loginLogOutput<<buf<<endl; } else { //no user...info... debug("login ip:"<<pclient->GetPeerName().ToString()); debug("no user %d %s info in out database !"<<req.uid<<req.emailAddr); } delete userinfo; //clean resources used above. } break; }//end of case case COMMIT_KEYS_REQUEST: { printf("recv a commit keys request from %d \n",kmsghead.src); RawData reqdata(pbuf,rt); CommitKeysRequest req; string upasswd=userdb->getUserPasswd(kmsghead.src); req.decryptAndUnserialize(reqdata,upasswd.c_str(),upasswd.length()); string pubKey(req.pubKey.data,req.pubKey.len); string privKey(req.privKey.data,req.privKey.len); bool rtv=userdb->putUserKeys(req.head.src,pubKey,privKey); CommitKeysReply reply; reply.head.status=(rtv)?0:-1; RawData replydata=reply.serialize(); pclient->SendPacket(replydata.data,replydata.len); break; }//end of case case PUBLIC_KEY_REQUEST: { debug("recv a public key request from %d"<<kmsghead.src); RawData reqdata(pbuf,rt); PublicKeyRequest req; req.unserialize(reqdata); string pubKey,privKey; bool rtv=userdb->getUserKeys(req.uid,pubKey,privKey); PublicKeyReply reply; reply.pubKey.set(pubKey.c_str(),pubKey.length()); reply.head.status=(rtv)?0:-1; RawData replydata=reply.serialize(); pclient->SendPacket(replydata.data,replydata.len); break; }//end of case case PRIVATE_KEY_REQUEST: { debug("recv a private key request from %d "<<kmsghead.src); RawData reqdata(pbuf,rt); PrivateKeyRequest req; req.unserialize(reqdata); string upasswd=userdb->getUserPasswd(kmsghead.src); string pubKey,privKey; bool rtv=userdb->getUserKeys(kmsghead.src,pubKey,privKey); PrivateKeyReply reply; reply.privKey.set(privKey.c_str(),privKey.length()); RawData replydata=reply.serializeAndEncrypt(upasswd.c_str(),upasswd.length()); pclient->SendPacket(replydata.data,replydata.len); break; } default: break; }//end switch(); }//end if(kmsghead.unserialize().... }
void SecureServer::generateCertificate(const std::string& publicKey, const std::string& privateKey, const std::string& password, const long& secsValid, const std::vector<std::pair<std::string,std::string> >& x509Entries, const std::string& x509Filename) throw (boost::system::system_error) { std::cerr << "generating certificate" << std::endl; std::unique_ptr<X509,void (*)(X509*)> x509(X509_new(), &X509_free); if(ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), std::time(nullptr)) != 1){ throw_system_error_ssl("Could not set X509 parameters"); } X509_gmtime_adj(X509_get_notBefore(x509.get()), 0); X509_gmtime_adj(X509_get_notAfter(x509.get()), secsValid); std::unique_ptr<EVP_PKEY,void(*)(EVP_PKEY*)> privKey(EVP_PKEY_new(), &EVP_PKEY_free); std::unique_ptr<EVP_PKEY,void(*)(EVP_PKEY*)> pubKey(EVP_PKEY_new(), &EVP_PKEY_free); std::unique_ptr<BIO,void (*)(BIO*)> privateBIO(BIO_new_file(privateKey.c_str(), "r"), &BIO_free_all); if(!privateBIO){ throw_system_error_ssl("Could not open "+privateKey+" for reading"); } pem_password_cb* password_cb(nullptr); void *password_u(nullptr); if(!password.empty()){ password_cb = &pemPasswordCBFromString; password_u = (void*)&password; } std::unique_ptr<RSA,void(*)(RSA*)> rsa(PEM_read_bio_RSAPrivateKey(privateBIO.get(), nullptr, password_cb, password_u),&RSA_free); if(!rsa){ throw_system_error_ssl("Could not read PEM RSA private key from "+privateKey); } std::cerr << "read " << privateKey << std::endl; if(EVP_PKEY_set1_RSA(privKey.get(), rsa.get()) != 1){ throw_system_error_ssl("Could not assign EVP_PKEY from RSA private key"); } std::cerr << "assigned EVP_PKEY" << std::endl; std::unique_ptr<BIO,void (*)(BIO*)> publicBIO(BIO_new_file(publicKey.c_str(), "r"), &BIO_free_all); if(!publicBIO){ throw_system_error_ssl("Could not open "+publicKey+" for reading"); } RSA *ptr = rsa.get(); if(PEM_read_bio_RSAPublicKey(publicBIO.get(),&ptr,nullptr,nullptr) == nullptr){ throw_system_error_ssl("Could not read PEM RSA public key from "+publicKey); } std::cerr << "read " << publicKey << std::endl; if(EVP_PKEY_set1_RSA(pubKey.get(), rsa.get()) != 1){ throw_system_error_ssl("Could not assign EVP_PKEY from RSA public key"); } if(X509_set_pubkey(x509.get(), pubKey.get()) != 1){ throw_system_error_ssl("Could nost assign X509 public key from EVP_PKEY"); } X509_NAME *name = X509_get_subject_name(x509.get()); std::cerr << "got subject name" << std::endl; for(const std::pair<std::string,std::string>& entry : x509Entries){ if(X509_NAME_add_entry_by_txt(name, entry.first.c_str(), MBSTRING_ASC, (const unsigned char*)entry.second.c_str(), entry.second.length(), -1, 0) != 1){ throw_system_error_ssl("Could not add X509 entry /"+entry.first+"/ = \""+entry.second+'"'); } std::cerr << "added entry /" << entry.first << "/ = \"" << entry.second << '"' << std::endl; } if(X509_set_issuer_name(x509.get(),name) != 1){ throw_system_error_ssl("Could not set X509 issuer name"); } std::cerr << "set issuer name" << std::endl; std::unique_ptr<EVP_MD_CTX,void(*)(EVP_MD_CTX*)> mctx(EVP_MD_CTX_create(),&EVP_MD_CTX_destroy); // EVP_PKEY_CTX *pkctx(nullptr); if(EVP_DigestSignInit(mctx.get(),nullptr,EVP_sha256(),nullptr,privKey.get()) != 1){ throw_system_error_ssl("Could not init EVP Digest Sign"); } std::cerr << "initialized EVP MD CTX" << std::endl; if(X509_sign_ctx(x509.get(),mctx.get()) <= 0){ throw_system_error_ssl("Could not sign certificate"); } std::cerr << "signed" << std::endl; std::unique_ptr<BIO,void(*)(BIO*)> x509BIO(BIO_new_file(x509Filename.c_str(),"w"),&BIO_free_all); if(PEM_write_bio_X509(x509BIO.get(),x509.get()) != 1){ throw_system_error_ssl("Could not write X509 certificate"); } std::cerr << "written to " << x509Filename << std::endl; }
KdeConnectConfig::KdeConnectConfig() : d(new KdeConnectConfigPrivate) { //qCDebug(KDECONNECT_CORE) << "QCA supported capabilities:" << QCA::supportedFeatures().join(","); if(!QCA::isSupported("rsa")) { qCritical() << "Could not find support for RSA in your QCA installation"; Daemon::instance()->reportError( i18n("KDE Connect failed to start"), i18n("Could not find support for RSA in your QCA installation. If your " "distribution provides separate packages for QCA-ossl and QCA-gnupg, " "make sure you have them installed and try again.")); return; } //Make sure base directory exists QDir().mkpath(baseConfigDir().path()); //.config/kdeconnect/config d->config = new QSettings(baseConfigDir().absoluteFilePath(QStringLiteral("config")), QSettings::IniFormat); d->trusted_devices = new QSettings(baseConfigDir().absoluteFilePath(QStringLiteral("trusted_devices")), QSettings::IniFormat); //Register my own id if not there yet if (!d->config->contains(QStringLiteral("id"))) { QString uuid = QUuid::createUuid().toString(); DbusHelper::filterNonExportableCharacters(uuid); d->config->setValue(QStringLiteral("id"), uuid); d->config->sync(); qCDebug(KDECONNECT_CORE) << "My id:" << uuid; } const QFile::Permissions strict = QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser; QString keyPath = privateKeyPath(); QFile privKey(keyPath); if (privKey.exists() && privKey.open(QIODevice::ReadOnly)) { d->privateKey = QCA::PrivateKey::fromPEM(privKey.readAll()); } else { d->privateKey = QCA::KeyGenerator().createRSA(2048); if (!privKey.open(QIODevice::ReadWrite | QIODevice::Truncate)) { Daemon::instance()->reportError(QStringLiteral("KDE Connect"), i18n("Could not store private key file: %1", keyPath)); } else { privKey.setPermissions(strict); privKey.write(d->privateKey.toPEM().toLatin1()); } } QString certPath = certificatePath(); QFile cert(certPath); if (cert.exists() && cert.open(QIODevice::ReadOnly)) { d->certificate = QSslCertificate::fromPath(certPath).at(0); } else { // FIXME: We only use QCA here to generate the cert and key, would be nice to get rid of it completely. // The same thing we are doing with QCA could be done invoking openssl (altought it's potentially less portable): // openssl req -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout privateKey.pem -days 3650 -out certificate.pem -subj "/O=KDE/OU=KDE Connect/CN=_e6e29ad4_2b31_4b6d_8f7a_9872dbaa9095_" QCA::CertificateOptions certificateOptions = QCA::CertificateOptions(); QDateTime startTime = QDateTime::currentDateTime().addYears(-1); QDateTime endTime = startTime.addYears(10); QCA::CertificateInfo certificateInfo; certificateInfo.insert(QCA::CommonName,deviceId()); certificateInfo.insert(QCA::Organization,QStringLiteral("KDE")); certificateInfo.insert(QCA::OrganizationalUnit,QStringLiteral("Kde connect")); certificateOptions.setInfo(certificateInfo); certificateOptions.setFormat(QCA::PKCS10); certificateOptions.setSerialNumber(QCA::BigInteger(10)); certificateOptions.setValidityPeriod(startTime, endTime); d->certificate = QSslCertificate(QCA::Certificate(certificateOptions, d->privateKey).toPEM().toLatin1()); if (!cert.open(QIODevice::ReadWrite | QIODevice::Truncate)) { Daemon::instance()->reportError(QStringLiteral("KDE Connect"), i18n("Could not store certificate file: %1", certPath)); } else { cert.setPermissions(strict); cert.write(d->certificate.toPem()); } } //Extra security check if (QFile::permissions(keyPath) != strict) { qCWarning(KDECONNECT_CORE) << "Warning: KDE Connect private key file has too open permissions " << keyPath; } }
SECKEYPrivateKey* CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { if (!aJwk.mKty.WasPassed() || !aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) { return nullptr; } // Verify that all of the required parameters are present CryptoBuffer n, e, d, p, q, dp, dq, qi; if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) || !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value())) || !aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value())) || !aJwk.mP.WasPassed() || NS_FAILED(p.FromJwkBase64(aJwk.mP.Value())) || !aJwk.mQ.WasPassed() || NS_FAILED(q.FromJwkBase64(aJwk.mQ.Value())) || !aJwk.mDp.WasPassed() || NS_FAILED(dp.FromJwkBase64(aJwk.mDp.Value())) || !aJwk.mDq.WasPassed() || NS_FAILED(dq.FromJwkBase64(aJwk.mDq.Value())) || !aJwk.mQi.WasPassed() || NS_FAILED(qi.FromJwkBase64(aJwk.mQi.Value()))) { return nullptr; } // Compute the ID for this key // This is generated with a SHA-1 hash, so unlikely to collide ScopedSECItem nItem(n.ToSECItem()); ScopedSECItem objID(PK11_MakeIDFromPubKey(nItem.get())); if (!nItem.get() || !objID.get()) { return nullptr; } // Populate template from parameters CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY; CK_KEY_TYPE rsaValue = CKK_RSA; CK_BBOOL falseValue = CK_FALSE; CK_ATTRIBUTE keyTemplate[14] = { { CKA_CLASS, &privateKeyValue, sizeof(privateKeyValue) }, { CKA_KEY_TYPE, &rsaValue, sizeof(rsaValue) }, { CKA_TOKEN, &falseValue, sizeof(falseValue) }, { CKA_SENSITIVE, &falseValue, sizeof(falseValue) }, { CKA_PRIVATE, &falseValue, sizeof(falseValue) }, { CKA_ID, objID->data, objID->len }, { CKA_MODULUS, (void*) n.Elements(), n.Length() }, { CKA_PUBLIC_EXPONENT, (void*) e.Elements(), e.Length() }, { CKA_PRIVATE_EXPONENT, (void*) d.Elements(), d.Length() }, { CKA_PRIME_1, (void*) p.Elements(), p.Length() }, { CKA_PRIME_2, (void*) q.Elements(), q.Length() }, { CKA_EXPONENT_1, (void*) dp.Elements(), dp.Length() }, { CKA_EXPONENT_2, (void*) dq.Elements(), dq.Length() }, { CKA_COEFFICIENT, (void*) qi.Elements(), qi.Length() }, }; // Create a generic object with the contents of the key ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot.get()) { return nullptr; } ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot.get(), keyTemplate, PR_ARRAY_SIZE(keyTemplate), PR_FALSE)); if (!obj.get()) { return nullptr; } // Have NSS translate the object to a private key by inspection // and make a copy we can own ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), objID.get(), nullptr)); if (!privKey.get()) { return nullptr; } return SECKEY_CopyPrivateKey(privKey.get()); }