Beispiel #1
0
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;
    }
}
Beispiel #5
0
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());
}