1 /*
2  * Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 #ifndef RNP_CFG_H_
27 #define RNP_CFG_H_
28 
29 #include <stdbool.h>
30 #include <stdint.h>
31 #include <string>
32 #include <vector>
33 #include <unordered_map>
34 
35 /* cfg variables known by rnp */
36 #define CFG_OVERWRITE "overwrite" /* overwrite output file if it is already exist or fail */
37 #define CFG_ARMOR "armor"         /* armor output data or not */
38 #define CFG_ARMOR_DATA_TYPE "armor_type" /* armor data type, used with ``enarmor`` option */
39 #define CFG_COMMAND "command"            /* command to execute over input data */
40 #define CFG_DETACHED "detached"          /* produce the detached signature */
41 #define CFG_CLEARTEXT "cleartext"        /* cleartext signing should be used */
42 #define CFG_SIGN_NEEDED "sign_needed"    /* signing is needed during data protection */
43 #define CFG_OUTFILE "outfile"            /* name/path of the output file */
44 #define CFG_NO_OUTPUT "no_output"        /* do not output any data - just verify or process */
45 #define CFG_INFILE "infile"              /* name/path of the input file */
46 #define CFG_RESULTS "results"            /* name/path for results, not used right now */
47 #define CFG_KEYSTOREFMT "keystorefmt"    /* keyring format : GPG, G10, KBX */
48 #define CFG_COREDUMPS "coredumps"        /* enable/disable core dumps. 1 or 0. */
49 #define CFG_NEEDSSECKEY "needsseckey"    /* needs secret key for the ongoing operation */
50 #define CFG_USERID "userid"              /* userid for the ongoing operation */
51 #define CFG_RECIPIENTS "recipients"      /* list of encrypted data recipients */
52 #define CFG_SIGNERS "signers"            /* list of signers */
53 #define CFG_HOMEDIR "homedir"            /* home directory - folder with keyrings and so on */
54 #define CFG_KEYFILE "keyfile"     /* path to the file with key(s), used instead of keyring */
55 #define CFG_PASSFD "pass-fd"      /* password file descriptor */
56 #define CFG_PASSWD "password"     /* password as command-line constant */
57 #define CFG_PASSWORDC "passwordc" /* number of passwords for symmetric encryption */
58 #define CFG_USERINPUTFD "user-input-fd" /* user input file descriptor */
59 #define CFG_NUMTRIES "numtries"         /* number of password request tries, or 'unlimited' */
60 #define CFG_EXPIRATION "expiration"     /* signature expiration time */
61 #define CFG_CREATION "creation"         /* signature validity start */
62 #define CFG_CIPHER "cipher"             /* symmetric encryption algorithm as string */
63 #define CFG_HASH "hash"                 /* hash algorithm used, string like 'SHA1'*/
64 #define CFG_S2K_ITER "s2k-iter"         /* number of S2K hash iterations to perform */
65 #define CFG_S2K_MSEC "s2k-msec"         /* number of milliseconds S2K should target */
66 #define CFG_ENCRYPT_PK "encrypt_pk"     /* public key should be used during encryption */
67 #define CFG_ENCRYPT_SK "encrypt_sk"     /* password encryption should be used */
68 #define CFG_IO_RESS "ress"              /* results stream */
69 #define CFG_NUMBITS "numbits"           /* number of bits in generated key */
70 #define CFG_EXPERT "expert"             /* expert key generation mode */
71 #define CFG_ZLEVEL "zlevel"             /* compression level: 0..9 (0 for no compression) */
72 #define CFG_ZALG "zalg"                 /* compression algorithm: zip, zlib or bzip2 */
73 #define CFG_AEAD "aead"                 /* if nonzero then AEAD enryption mode, int */
74 #define CFG_AEAD_CHUNK "aead_chunk"     /* AEAD chunk size bits, int from 0 to 56 */
75 #define CFG_KEYSTORE_DISABLED \
76     "disable_keystore"              /* indicates whether keystore must be initialized */
77 #define CFG_FORCE "force"           /* force command to succeed operation */
78 #define CFG_SECRET "secret"         /* indicates operation on secret key */
79 #define CFG_WITH_SIGS "with-sigs"   /* list keys with signatures */
80 #define CFG_JSON "json"             /* list packets with JSON output */
81 #define CFG_GRIPS "grips"           /* dump grips when dumping key packets */
82 #define CFG_MPIS "mpis"             /* dump MPI values when dumping packets */
83 #define CFG_RAW "raw"               /* dump raw packet contents */
84 #define CFG_REV_TYPE "rev-type"     /* revocation reason code */
85 #define CFG_REV_REASON "rev-reason" /* revocation reason human-readable string */
86 #define CFG_PERMISSIVE "permissive" /* ignore bad packets during key import */
87 #define CFG_NOTTY "notty" /* disable tty usage and do input/output via stdin/stdout */
88 #define CFG_FIX_25519_BITS "fix-25519-bits"   /* fix Cv25519 secret key via --edit-key */
89 #define CFG_CHK_25519_BITS "check-25519-bits" /* check Cv25519 secret key bits */
90 
91 /* rnp keyring setup variables */
92 #define CFG_KR_PUB_FORMAT "kr-pub-format"
93 #define CFG_KR_SEC_FORMAT "kr-sec-format"
94 #define CFG_KR_PUB_PATH "kr-pub-path"
95 #define CFG_KR_SEC_PATH "kr-sec-path"
96 #define CFG_KR_DEF_KEY "kr-def-key"
97 
98 /* key generation variables */
99 #define CFG_KG_PRIMARY_ALG "kg-primary-alg"
100 #define CFG_KG_PRIMARY_BITS "kg-primary-bits"
101 #define CFG_KG_PRIMARY_CURVE "kg-primary-curve"
102 #define CFG_KG_PRIMARY_EXPIRATION "kg-primary-expiration"
103 #define CFG_KG_SUBKEY_ALG "kg-subkey-alg"
104 #define CFG_KG_SUBKEY_BITS "kg-subkey-bits"
105 #define CFG_KG_SUBKEY_CURVE "kg-subkey-curve"
106 #define CFG_KG_SUBKEY_EXPIRATION "kg-subkey-expiration"
107 #define CFG_KG_HASH "kg-hash"
108 #define CFG_KG_PROT_HASH "kg-prot-hash"
109 #define CFG_KG_PROT_ALG "kg-prot-alg"
110 #define CFG_KG_PROT_ITERATIONS "kg-prot-iterations"
111 
112 /* rnp CLI config : contains all the system-dependent and specified by the user configuration
113  * options */
114 class rnp_cfg_val;
115 
116 class rnp_cfg {
117   private:
118     std::unordered_map<std::string, rnp_cfg_val *> vals_;
119     std::string                                    empty_str_;
120 
121     /** @brief Parse date from the string in %Y-%m-%d format (using "-", "/", "." as a
122      * separator)
123      *
124      *  @param s string with the date
125      *  @param t UNIX timestamp of successfully parsed date
126      *  @return true when parsed successfully or false otherwise
127      */
128     bool parse_date(const std::string &s, uint64_t &t) const;
129 
130   public:
131     /** @brief load default settings */
132     void load_defaults();
133     /** @brief set string value for the key in config */
134     void set_str(const std::string &key, const std::string &val);
135     void set_str(const std::string &key, const char *val);
136     /** @brief set int value for the key in config */
137     void set_int(const std::string &key, int val);
138     /** @brief set bool value for the key in config */
139     void set_bool(const std::string &key, bool val);
140     /** @brief remove key and corresponding value from the config */
141     void unset(const std::string &key);
142     /** @brief add string item to the list value */
143     void add_str(const std::string &key, const std::string &val);
144     /** @brief check whether config has value for the key */
145     bool has(const std::string &key) const;
146     /** @brief get string value from the config. If it is absent then empty string will be
147      *         returned */
148     const std::string &get_str(const std::string &key) const;
149     /** @brief get C string value from the config. Will return 0 instead of empty string if
150      * value is absent. */
151     const char *get_cstr(const std::string &key) const;
152     /** @brief get int value from the config. If it is absent then def will be returned */
153     int get_int(const std::string &key, int def = 0) const;
154     /** @brief get bool value from the config. If it is absent then false will be returned */
155     bool get_bool(const std::string &key) const;
156     /** @brief get number of items in the string list value. If it is absent then 0 will be
157      *         returned. */
158     size_t get_count(const std::string &key) const;
159     /** @brief get string from the list value at the corresponding position. If there is no
160      *         corresponding value or index too large then empty string will be returned. */
161     const std::string &get_str(const std::string &key, size_t idx) const;
162     /** @brief get all strings from the list value */
163     std::vector<std::string> get_list(const std::string &key) const;
164     /** @brief get number of the password tries */
165     int get_pswdtries() const;
166     /** @brief get hash algorithm */
167     const std::string get_hashalg() const;
168 
169     /** @brief Get expiration time from the cfg variable, as value relative to the current
170      * time. As per OpenPGP standard it should fit in 32 bit value, otherwise error is
171      * returned.
172      *
173      *  Expiration may be specified in different formats:
174      *  - 10d : 10 days (you can use [h]ours, d[ays], [w]eeks, [m]onthes)
175      *  - 2017-07-12 : as the exact date
176      *  - 60000 : number of seconds
177      *
178      *  @param seconds On successfull return result will be placed here
179      *  @return true on success or false otherwise
180      */
181     bool get_expiration(const std::string &key, uint32_t &seconds) const;
182 
183     /** @brief Get signature creation time from the config.
184      *  Creation time may be specified in different formats:
185      *  - 2017-07-12 : as the exact date
186      *  - 1499334073 : timestamp
187      *
188      *  @return timestamp of the signature creation.
189      */
190     uint64_t get_sig_creation() const;
191     /** @brief copy or override a configuration.
192      *  @param src vals will be overridden (if key exist) or copied (if not) from this object
193      */
194     void copy(const rnp_cfg &src);
195     void clear();
196     /* delete unneeded operators */
197     rnp_cfg &operator=(const rnp_cfg &src) = delete;
198     rnp_cfg &operator=(const rnp_cfg &&src) = delete;
199     /** @brief destructor */
200     ~rnp_cfg();
201 };
202 
203 #endif
204