Esempio n. 1
0
// deleteUID deletes a nym.
func (ce *CryptEngine) deleteUID(pseudonym string, force bool) error {
	// map pseudonym
	id, err := identity.Map(pseudonym)
	if err != nil {
		return err
	}

	// get UID from keyDB
	msg, _, err := ce.keyDB.GetPrivateUID(id, false)
	if err != nil {
		return err
	}

	// ask for manual confirmation
	if !force {
		fmt.Fprintf(os.Stderr, "cryptengine: delete user ID %s and all it's key material? ",
			pseudonym)
		var response string
		_, err := fmt.Scanln(&response)
		if err != nil {
			return log.Error(err)
		}
		if !strings.HasPrefix(strings.ToLower(response), "y") {
			return log.Error("cryptengine: user ID deletion aborted")
		}
	}

	// delete UID from keyDB
	if err := ce.keyDB.DelPrivateUID(msg); err != nil {
		return err
	}
	return nil
}
Esempio n. 2
0
func (ce *CtrlEngine) msgRead(w io.Writer, myID string, msgID int64) error {
	idMapped, err := identity.Map(myID)
	if err != nil {
		return err
	}
	from, to, msg, date, err := ce.msgDB.GetMessage(idMapped, msgID)
	if err != nil {
		return err
	}
	if err := ce.msgDB.ReadMessage(msgID); err != nil {
		return err
	}
	subject, message := mimeMsg.SplitMessage(msg)
	fmt.Fprintf(w, "Date: %s\r\n",
		time.Unix(date, 0).UTC().Format(time.RFC1123Z))
	fmt.Fprintf(w, "From: %s\r\n", from)
	fmt.Fprintf(w, "To: %s\r\n", to)
	if subject != "" {
		fmt.Fprintf(w, "Subject: %s\r\n", mime.QEncoding.Encode("utf-8", subject))
	}
	fmt.Fprintf(w, "MIME-Version: 1.0\r\n")
	fmt.Fprintf(w, "Content-Type: text/plain; charset=UTF-8\r\n")
	fmt.Fprintf(w, "\r\n")
	fmt.Fprintf(w, "%s", message)
	return nil
}
Esempio n. 3
0
// encrypt reads data from r, encrypts it for identity to (with identity from
// as sender), and writes it to w.
func (ce *CryptEngine) encrypt(
	w io.Writer,
	from, to string,
	sign bool,
	nymAddress string,
	r io.Reader,
	statusfp *os.File,
) error {
	// map pseudonyms
	fromID, fromDomain, err := identity.MapPlus(from)
	if err != nil {
		return err
	}
	toID, err := identity.Map(to)
	if err != nil {
		return err
	}
	// get fromUID from keyDB
	fromUID, _, err := ce.keyDB.GetPrivateUID(fromID, true)
	if err != nil {
		return err
	}
	// get toUID from keyDB
	toUID, _, found, err := ce.keyDB.GetPublicUID(toID, math.MaxInt64) // TODO: use simpler API
	if err != nil {
		return err
	}
	if !found {
		return log.Errorf("not UID for '%s' found", toID)
	}
	// encrypt message
	senderLastKeychainHash, err := ce.keyDB.GetLastHashChainEntry(fromDomain)
	if err != nil {
		return err
	}
	var privateSigKey *[64]byte
	if sign {
		privateSigKey = fromUID.PrivateSigKey64()
	}
	args := &msg.EncryptArgs{
		Writer:                 w,
		From:                   fromUID,
		To:                     toUID,
		NymAddress:             nymAddress,
		SenderLastKeychainHash: senderLastKeychainHash,
		PrivateSigKey:          privateSigKey,
		Reader:                 r,
		Rand:                   cipher.RandReader,
		KeyStore:               ce,
	}
	nymAddress, err = msg.Encrypt(args)
	if err != nil {
		return err
	}
	// show nymaddress on status-fd
	fmt.Fprintf(statusfp, "NYMADDRESS:\t%s\n", nymAddress)
	return nil
}
Esempio n. 4
0
func (ce *CtrlEngine) msgDelete(myID string, msgID int64) error {
	idMapped, err := identity.Map(myID)
	if err != nil {
		return err
	}
	if err := ce.msgDB.DelMessage(idMapped, msgID); err != nil {
		return err
	}
	return nil
}
Esempio n. 5
0
func (ce *CtrlEngine) uidSwitch(unmappedID string) error {
	mappedID, err := identity.Map(unmappedID)
	if err != nil {
		return err
	}
	existing, _, err := ce.msgDB.GetNym(mappedID)
	if err != nil {
		return err
	}
	if existing == "" {
		return log.Errorf("user ID %s unknown", unmappedID)
	}
	if err := ce.msgDB.AddValue(msgdb.ActiveUID, mappedID); err != nil {
		return err
	}
	return nil
}
Esempio n. 6
0
func (ce *CtrlEngine) uidEdit(unmappedID, fullName string) error {
	mappedID, err := identity.Map(unmappedID)
	if err != nil {
		return err
	}
	old, _, err := ce.msgDB.GetNym(mappedID)
	if err != nil {
		return err
	}
	if old == "" {
		return log.Errorf("user ID %s unknown", unmappedID)
	}
	if err := ce.msgDB.AddNym(mappedID, unmappedID, fullName); err != nil {
		return err
	}
	return nil
}
Esempio n. 7
0
// AddContact adds or updates a contact in msgDB.
func (msgDB *MsgDB) AddContact(
	myID, mappedID, unmappedID, fullName string,
	contactType ContactType,
) error {
	if err := identity.IsMapped(myID); err != nil {
		return log.Error(err)
	}
	if err := identity.IsMapped(mappedID); err != nil {
		return log.Error(err)
	}
	if unmappedID == "" {
		return log.Error("msgdb: unmappedID must be defined")
	}
	// make sure mappedID and unmappedID fit together
	mID, err := identity.Map(unmappedID)
	if err != nil {
		return log.Error(err)
	}
	if mID != mappedID {
		return log.Errorf("msgdb: identity.Map(%s) != %s", unmappedID, mappedID)
	}
	// get MyID
	var uid int
	if err := msgDB.getNymUIDQuery.QueryRow(myID).Scan(&uid); err != nil {
		return log.Error(err)
	}
	// add contact
	res, err := msgDB.updateContactQuery.Exec(unmappedID, fullName, contactType,
		uid, mappedID)
	if err != nil {
		return log.Error(err)
	}
	nRows, err := res.RowsAffected()
	if err != nil {
		return log.Error(err)
	}
	if nRows == 0 {
		_, err := msgDB.insertContactQuery.Exec(uid, mappedID, unmappedID,
			fullName, contactType)
		if err != nil {
			return log.Error(err)
		}
	}
	return nil
}
Esempio n. 8
0
func (ce *CtrlEngine) msgList(w io.Writer, id string) error {
	idMapped, err := identity.Map(id)
	if err != nil {
		return err
	}
	ids, err := ce.msgDB.GetMsgIDs(idMapped)
	if err != nil {
		return err
	}
	for _, id := range ids {
		var (
			direction rune
			status    rune
		)
		if id.Incoming {
			direction = '>'
			if id.Read {
				status = 'R'
			} else {
				status = 'N'
			}
		} else {
			direction = '<'
			if id.Sent {
				status = 'S'
			} else {
				status = 'P'
			}
		}
		fmt.Fprintf(w, "%c%c %d\t%s\t%s\t%s\t%s\n",
			direction,
			status,
			id.MsgID,
			time.Unix(id.Date, 0).Format(time.RFC3339),
			id.From,
			id.To,
			id.Subject)
	}
	return nil
}
Esempio n. 9
0
// genupdate generates an update for the (registered) nym and stores it in keydb.
func (ce *CryptEngine) genupdate(pseudonym string) error {
	// map pseudonym
	id, err := identity.Map(pseudonym)
	if err != nil {
		return err
	}
	// get old UID from keyDB
	oldUID, _, err := ce.keyDB.GetPrivateUID(id, true)
	if err != nil {
		return err
	}
	// generate new UID
	newUID, err := oldUID.Update(cipher.RandReader)
	if err != nil {
		return err
	}
	// store new UID in keyDB
	if err := ce.keyDB.AddPrivateUID(newUID); err != nil {
		return err
	}
	return nil
}
Esempio n. 10
0
func (ce *CtrlEngine) upkeepAll(
	c *cli.Context,
	unmappedID,
	period string,
	statfp io.Writer,
) error {
	mappedID, err := identity.Map(unmappedID)
	if err != nil {
		return err
	}

	exec, now, err := checkExecution(mappedID, period,
		func(mappedID string) (int64, error) {
			return ce.msgDB.GetUpkeepAll(mappedID)
		})
	if err != nil {
		return err
	}
	if !exec {
		log.Info(statfp, "ctrlengine: upkeep all not due")
		fmt.Fprintf(statfp, "ctrlengine: upkeep all not due\n")
		return nil
	}

	// `upkeep accounts`
	if err := ce.upkeepAccounts(unmappedID, period, "2160h", statfp); err != nil {
		return err
	}

	// TODO: call all upkeep tasks in mutecrypt

	// record time of execution
	if err := ce.msgDB.SetUpkeepAll(mappedID, now); err != nil {
		return err
	}
	return nil
}
Esempio n. 11
0
// AddNym adds or updates a mapping from a mapped ID to an unmapped ID and
// full name.
func (msgDB *MsgDB) AddNym(mappedID, unmappedID, fullName string) error {
	if mappedID == "" {
		return log.Error("msgdb: mappedID must be defined")
	}
	if unmappedID == "" {
		return log.Error("msgdb: unmappedID must be defined")
	}
	// make sure the mappedID is mapped
	if err := identity.IsMapped(mappedID); err != nil {
		return log.Error(err)
	}
	// make sure mappedID and unmappedID fit together
	mID, err := identity.Map(unmappedID)
	if err != nil {
		return log.Error(err)
	}
	if mID != mappedID {
		return log.Errorf("msgdb: identity.Map(%s) != %s", unmappedID, mappedID)
	}
	// fullName can be empty
	res, err := msgDB.updateNymQuery.Exec(unmappedID, fullName, mappedID)
	if err != nil {
		return log.Error(err)
	}
	nRows, err := res.RowsAffected()
	if err != nil {
		return log.Error(err)
	}
	if nRows == 0 {
		_, err := msgDB.insertNymQuery.Exec(mappedID, unmappedID, fullName)
		if err != nil {
			return log.Error(err)
		}
	}
	return nil
}
Esempio n. 12
0
func (ce *CtrlEngine) getNyms(id string, all bool) ([]string, error) {
	var nyms []string
	if all {
		ids, err := ce.msgDB.GetNyms(true)
		if err != nil {
			return nil, err
		}
		nyms = append(nyms, ids...)
	} else {
		idMapped, err := identity.Map(id)
		if err != nil {
			return nil, err
		}
		prev, _, err := ce.msgDB.GetNym(idMapped)
		if err != nil {
			return nil, err
		}
		if prev == "" {
			return nil, log.Errorf("user ID %s not found", id)
		}
		nyms = append(nyms, idMapped)
	}
	return nyms, nil
}
Esempio n. 13
0
func (ce *CtrlEngine) upkeepAccounts(
	unmappedID, period, remaining string,
	statfp io.Writer,
) error {
	mappedID, err := identity.Map(unmappedID)
	if err != nil {
		return err
	}

	exec, now, err := checkExecution(mappedID, period,
		func(mappedID string) (int64, error) {
			return ce.msgDB.GetUpkeepAccounts(mappedID)
		})
	if err != nil {
		return err
	}
	if !exec {
		log.Info(statfp, "ctrlengine: upkeep accounts not due")
		fmt.Fprintf(statfp, "ctrlengine: upkeep accounts not due\n")
		return nil
	}

	remain, err := time.ParseDuration(remaining)
	if err != nil {
		return err
	}

	contacts, err := ce.msgDB.GetAccounts(mappedID)
	if err != nil {
		return err
	}

	for _, contact := range contacts {
		privkey, server, _, _, _, _, err := ce.msgDB.GetAccount(mappedID, contact)
		if err != nil {
			return err
		}
		last, err := ce.msgDB.GetAccountTime(mappedID, contact)
		if err != nil {
			return err
		}
		if last == 0 {
			last, err = mixclient.AccountStat(privkey, server, def.CACert)
			if err != nil {
				return err
			}
			err := ce.msgDB.SetAccountTime(mappedID, contact, last)
			if err != nil {
				return err
			}
		}
		if times.Now()+int64(remain.Seconds()) >= last {
			token, err := wallet.GetToken(ce.client, def.AccdUsage, def.AccdOwner)
			if err != nil {
				return err
			}
			_, err = mixclient.PayAccount(privkey, token.Token, server, def.CACert)
			if err != nil {
				ce.client.UnlockToken(token.Hash)
				return log.Error(err)
			}
			ce.client.DelToken(token.Hash)
			last, err = mixclient.AccountStat(privkey, server, def.CACert)
			if err != nil {
				return err
			}
			err = ce.msgDB.SetAccountTime(mappedID, contact, last)
			if err != nil {
				return err
			}
		}
	}

	// record time of execution
	if err := ce.msgDB.SetUpkeepAccounts(mappedID, now); err != nil {
		return err
	}

	return nil
}
Esempio n. 14
0
func (ce *CtrlEngine) msgAdd(
	c *cli.Context,
	from, to, file string,
	mailInput, permanentSignature bool,
	attachments []string,
	minDelay, maxDelay int32,
	line *liner.State,
	r io.Reader,
) error {
	fromMapped, err := identity.Map(from)
	if err != nil {
		return err
	}
	prev, _, err := ce.msgDB.GetNym(fromMapped)
	if err != nil {
		return err
	}
	if prev == "" {
		return log.Errorf("user ID %s not found", from)
	}

	// TODO: handle attachments
	var msg []byte
	if file != "" {
		// read message from file
		msg, err = ioutil.ReadFile(file)
		if err != nil {
			return log.Error(err)
		}
	} else if line != nil {
		// read message from terminal
		fmt.Fprintln(ce.fileTable.StatusFP,
			"type message (end with Ctrl-D on empty line):")
		var inbuf bytes.Buffer
		for {
			ln, err := line.Prompt("")
			if err != nil {
				if err == io.EOF {
					break
				}
				return log.Error(err)
			}
			inbuf.WriteString(ln + "\n")
		}
		msg = inbuf.Bytes()
	} else {
		// read message from stdin
		msg, err = ioutil.ReadAll(r)
		if err != nil {
			return log.Error(err)
		}
	}

	if mailInput {
		recipient, message, err := mail.Parse(bytes.NewBuffer(msg))
		if err != nil {
			return err
		}
		to = recipient
		msg = []byte(message)
	}

	toMapped, err := identity.Map(to)
	if err != nil {
		return err
	}
	prev, _, contactType, err := ce.msgDB.GetContact(fromMapped, toMapped)
	if err != nil {
		return err
	}
	if prev == "" || contactType == msgdb.GrayList || contactType == msgdb.BlackList {
		return log.Errorf("contact %s not found (for user ID %s)", to, from)
	}

	// store message in message DB
	now := times.Now()
	err = ce.msgDB.AddMessage(fromMapped, toMapped, now, true, string(msg),
		permanentSignature, minDelay, maxDelay)
	if err != nil {
		return err
	}

	log.Info("message added")
	if line != nil {
		fmt.Fprintln(ce.fileTable.StatusFP, "message added")
	}

	return nil
}
Esempio n. 15
0
func (ce *CtrlEngine) uidDelete(
	c *cli.Context,
	unmappedID string,
	force bool,
	statfp io.Writer,
) error {
	mappedID, err := identity.Map(unmappedID)
	if err != nil {
		return err
	}

	// make sure user ID is in message DB
	prev, _, err := ce.msgDB.GetNym(mappedID)
	if err != nil {
		return err
	}
	if prev == "" {
		return log.Errorf("ctrlengine: user ID '%s' unknown", unmappedID)
	}

	// ask for manual confirmation
	if !force {
		fmt.Fprintf(statfp, "ctrlengine: delete user ID %s and all contacts and messages? ",
			unmappedID)
		var response string
		_, err := fmt.Scanln(&response)
		if err != nil {
			return log.Error(err)
		}
		if !strings.HasPrefix(strings.ToLower(response), "y") {
			return log.Error("ctrlengine: user ID deletion aborted")
		}
	}

	// get account information before deletion
	contacts, err := ce.msgDB.GetAccounts(mappedID)
	if err != nil {
		return err
	}
	var privkeys []*[ed25519.PrivateKeySize]byte
	var servers []string
	for _, contact := range contacts {
		privkey, server, _, _, _, _, err := ce.msgDB.GetAccount(mappedID, contact)
		if err != nil {
			return err
		}
		privkeys = append(privkeys, privkey)
		servers = append(servers, server)
	}

	// remove user ID from message DB
	if err := ce.msgDB.DelNym(mappedID); err != nil {
		return err
	}

	// remove user ID from key DB
	if err := mutecryptDeleteUID(c, mappedID, ce.passphrase); err != nil {
		return err
	}

	// delete corresponding accounts. It doesn't matter that much, if this
	// fails because the accounts will expiry eventually.
	for i, privkey := range privkeys {
		err := mixclient.DeleteAccount(privkey, servers[i], def.CACert)
		if err != nil {
			return log.Error(err)
		}
	}

	return nil
}