Example #1
0
// Add responds to /pks/add HKP requests.
func (w *Worker) Add(a *hkp.Add) {
	// Parse armored keytext
	var changes []*KeyChange
	var readErrors []*ReadKeyResult
	// Check and decode the armor
	armorBlock, err := armor.Decode(bytes.NewBufferString(a.Keytext))
	if err != nil {
		a.Response() <- &ErrorResponse{err}
		return
	}

	for readKey := range ReadKeys(armorBlock.Body) {
		if readKey.Error != nil {
			readErrors = append(readErrors, readKey)
		} else {
			log.Println("add.go: Found a key from request!! = ", readKey.Pubkey.KeyId())
			//SignPubKeyPKS(*readKey.Pubkey)
			//First Check weather we are the authority for it
			underAuth := IsUnderAuth(*readKey.Pubkey)
			if underAuth != nil {
				change1 := &KeyChange{}
				change1.Type = NotInOurAuthority
				change1.ChangeMessage = underAuth.Error()
				changes = append(changes, change1)
				log.Println(underAuth.Error())
			} else {

				//Checked weather its under our own authority

				if readKey.Pubkey.Sha256 == a.ShaOfTarget || len(a.ShaOfTarget) != 64 {
					//Extract Email
					usrID := readKey.Pubkey.primaryUid
					userEmail := usrID.UserId.Email
					//Email extracted
					req_PubKey := readKey.Pubkey
					reqChanges := w.FindChanges(readKey.Pubkey)
					isVerified := false
					var otlState int
					if reqChanges.Type == KeyAdded {
						//Key not found hence new key added
						log.Println("add.go:Request has New Key (ID): ", req_PubKey.Fingerprint())

						isVerified, otlState = w.Verify(userEmail, a.Keytext, *req_PubKey, int16(1))
						log.Println("add.go:Is Requested Key Verified??: ", isVerified)

					} else if reqChanges.Type == KeyModified {
						//key will be changed/updated with new contents
						log.Println("add.go:Request Modifies key (ID): ", req_PubKey.Fingerprint())

						isVerified, otlState = w.Verify(userEmail, a.Keytext, *req_PubKey, int16(1))
						log.Println("add.go:Is Requested Key Verified??: ", isVerified)
					} else if reqChanges.Type == KeyNotChanged {
						log.Println("add.go:request doesnt make change to key(id) : ", req_PubKey.Fingerprint())

						w.notifyChange(reqChanges)
						changes = append(changes, reqChanges)
						a.Response() <- &AddResponse{Changes: changes, Errors: readErrors}
						return
					}

					if isVerified {
						if reqChanges.Type != KeyNotChanged {
							//If key is verified then call upsert as
							//it will eventually insert data in to db
							log.Println("add.go:Key Verified...")
							//Key verified hence add signature of PKS
							//Check weather a key with same email exists or not.
							repKeys, err := w.LookupKeys(userEmail, 2)
							replacesKey := false
							if err == ErrKeyNotFound || len(repKeys) <= 0 { //No key found by Email
								replacesKey = false
							} else {
								replacesKey = true
							}

							//Replace End

							//Signing Start
							signed_Key, err := SignKeyAfterVerification(a.Keytext)
							if err != nil {
								log.Println("Error signing key ", err)
								a.Response() <- &ErrorResponse{err}
								return
							}
							armorBlock, err := armor.Decode(bytes.NewBufferString(signed_Key))
							if err != nil {
								log.Println("decoding signed key ", err)
								a.Response() <- &ErrorResponse{err}
								return
							}

							for readKey := range ReadKeys(armorBlock.Body) {
								if readKey.Error != nil {
									readErrors = append(readErrors, readKey)
								} else {

									if _, err = w.Begin(); err != nil {
										a.Response() <- &ErrorResponse{err}
										return
									}
									change := w.UpsertKey(readKey.Pubkey)
									if err = w.Commit(); err != nil {
										a.Response() <- &ErrorResponse{err}
										return
									}
									//Signing END
									if change.Error != nil {
										log.Printf("Error updating key [%s]: %v\n", readKey.Pubkey.Fingerprint(),
											change.Error)
									} else {
										if replacesKey {
											//Delete Old key
											if _, err = w.Begin(); err != nil {
												log.Println("replaceDelete", err)
												a.Response() <- &ErrorResponse{err}
												return
											}
											change, err1 := w.deleteKey(repKeys[0])
											if err = w.Commit(); err != nil {
												log.Println("replaceDelete", err)
												a.Response() <- &ErrorResponse{err}
												return
											}

											if err1 != nil {
												log.Println("replaceDelete", err1)
												a.Response() <- &ErrorResponse{err1}
												return
											}

											w.notifyChange(&change)
											changes = append(changes, &change)
										}
									}

									//Notify using changes
									w.notifyChange(change)
									changes = append(changes, change)
								}
							}

						} else {
							w.notifyChange(reqChanges)
							changes = append(changes, reqChanges)
						}
					} else {
						reqChanges.Type = EmailNotVerified
						reqChanges.Fingerprint = ""
						if otlState == OTLNewOtlMade {
							resKeys, err := w.LookupKeys(userEmail, 2)
							replacesKey := false
							if err == ErrKeyNotFound || len(resKeys) <= 0 { //No key found by Email
								replacesKey = false
							} else {
								replacesKey = true
							}

							message := fmt.Sprintf("A verification link has been sent to %s.The link will expire in %d day/s.\n Please check your email.", userEmail, ExpInDays)
							if replacesKey {
								message += "		* A key with same email already exists on the server.If you verify above request it will replace the key with id " +
									strings.ToUpper(resKeys[0].KeyId())
							}
							reqChanges.ChangeMessage = message
							log.Println("OTL NOT FOUND!!")

						} else if otlState == OTLExpired {
							reqChanges.ChangeMessage = fmt.Sprintf("The link you have clicked has expired. Please submit your key again.")
							log.Println("OTL Expired!!")

						} else if otlState == OTLNotVerified {
							reqChanges.ChangeMessage = fmt.Sprintf("A request for same key has already been made.Please Check your email %s", userEmail)
							log.Println("OTL Not Verified!!")
						} else if otlState == ErrorSendingMail {
							reqChanges.ChangeMessage = fmt.Sprintf("Unfortunately we were unable to send an e-mail to %s Please Add key after sometime with new request", userEmail)
						}

						changes = append(changes, reqChanges)
					}

					//EDIT END

				}
				a.Response() <- &AddResponse{Changes: changes, Errors: readErrors}
				return
			}
			a.Response() <- &AddResponse{Changes: changes, Errors: readErrors}
			return
		}
	}
}