clang -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ipa_kdb_passwords.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/10.0.0 -D HAVE_CONFIG_H -I . -I ../.. -I . -I ../../util -D PREFIX="/usr/local" -D BINDIR="/usr/local/bin" -D LIBDIR="/usr/local/lib" -D LIBEXECDIR="/usr/local/libexec" -D DATADIR="/usr/local/share" -D LDAPIDIR="/run" -I /usr/include/samba-4.0 -D _GNU_SOURCE=1 -D HAVE_IMMEDIATE_STRUCTURES=1 -I /usr/include/nss3 -I /usr/include/nspr4 -I /usr/include/nspr4 -I /usr/include/nss3 -I /usr/include/nspr4 -D __STDC_WANT_LIB_EXT1__=1 -D _DEFAULT_SOURCE=1 -D _POSIX_C_SOURCE=200809L -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/10.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /home/heimes/redhat/freeipa/daemons/ipa-kdb -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -faddrsig -o /home/heimes/redhat/freeipa/report/2020-06-05-101548-295465-1 -x c ipa_kdb_passwords.c
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | #include "ipa_kdb.h" |
| 24 | #include "ipa_pwd.h" |
| 25 | #include <kadm5/kadm_err.h> |
| 26 | |
| 27 | static krb5_error_code ipapwd_error_to_kerr(krb5_context context, |
| 28 | enum ipapwd_error err) |
| 29 | { |
| 30 | krb5_error_code kerr; |
| 31 | |
| 32 | switch(err) { |
| 18 | | Control jumps to 'case IPAPWD_POLICY_OK:' at line 33 | |
|
| 33 | case IPAPWD_POLICY_OK: |
| 34 | kerr = 0; |
| 35 | break; |
| 19 | | Execution continues on line 61 | |
|
| 36 | case IPAPWD_POLICY_ACCOUNT_EXPIRED: |
| 37 | kerr = KADM5_BAD_PRINCIPAL; |
| 38 | krb5_set_error_message(context, kerr, "Account expired"); |
| 39 | break; |
| 40 | case IPAPWD_POLICY_PWD_TOO_YOUNG: |
| 41 | kerr = KADM5_PASS_TOOSOON; |
| 42 | krb5_set_error_message(context, kerr, "Too soon to change password"); |
| 43 | break; |
| 44 | case IPAPWD_POLICY_PWD_TOO_SHORT: |
| 45 | kerr = KADM5_PASS_Q_TOOSHORT; |
| 46 | krb5_set_error_message(context, kerr, "Password is too short"); |
| 47 | break; |
| 48 | case IPAPWD_POLICY_PWD_IN_HISTORY: |
| 49 | kerr = KADM5_PASS_REUSE; |
| 50 | krb5_set_error_message(context, kerr, "Password reuse not permitted"); |
| 51 | break; |
| 52 | case IPAPWD_POLICY_PWD_COMPLEXITY: |
| 53 | kerr = KADM5_PASS_Q_CLASS; |
| 54 | krb5_set_error_message(context, kerr, "Password is too simple"); |
| 55 | break; |
| 56 | default: |
| 57 | kerr = KADM5_PASS_Q_GENERIC; |
| 58 | break; |
| 59 | } |
| 60 | |
| 61 | return kerr; |
| 20 | | Returning zero (loaded from 'kerr'), which participates in a condition later | |
|
| 62 | } |
| 63 | |
| 64 | static krb5_error_code ipadb_check_pw_policy(krb5_context context, |
| 65 | char *passwd, |
| 66 | krb5_db_entry *db_entry) |
| 67 | { |
| 68 | krb5_error_code kerr; |
| 69 | struct ipadb_e_data *ied; |
| 70 | struct ipadb_context *ipactx; |
| 71 | int ret; |
| 72 | |
| 73 | ipactx = ipadb_get_context(context); |
| 74 | if (!ipactx) { |
| 7 | | Assuming 'ipactx' is non-null, which participates in a condition later | |
|
| |
| 75 | return KRB5_KDB_DBNOTINITED; |
| 76 | } |
| 77 | |
| 78 | ied = (struct ipadb_e_data *)db_entry->e_data; |
| 79 | if (ied->magic != IPA_E_DATA_MAGIC) { |
| 9 | | Assuming field 'magic' is equal to IPA_E_DATA_MAGIC | |
|
| |
| 80 | return EINVAL; |
| 81 | } |
| 82 | |
| 83 | if (strlen(passwd) > IPAPWD_PASSWORD_MAX_LEN) { |
| 11 | | Assuming the condition is false | |
|
| |
| 84 | krb5_set_error_message(context, E2BIG, "%s", |
| 85 | ipapwd_password_max_len_errmsg); |
| 86 | return E2BIG; |
| 87 | } |
| 88 | |
| 89 | ied->passwd = strdup(passwd); |
| 90 | if (!ied->passwd) { |
| 13 | | Assuming field 'passwd' is non-null, which participates in a condition later | |
|
| |
| 91 | return ENOMEM; |
| 92 | } |
| 93 | |
| 94 | kerr = ipadb_get_ipapwd_policy(ipactx, ied->pw_policy_dn, &ied->pol); |
| 95 | if (kerr != 0) { |
| 15 | | Assuming 'kerr' is equal to 0 | |
|
| |
| 96 | return kerr; |
| 97 | } |
| 98 | ret = ipapwd_check_policy(ied->pol, passwd, time(NULL), |
| 99 | db_entry->expiration, |
| 100 | db_entry->pw_expiration, |
| 101 | ied->last_pwd_change, |
| 102 | ied->pw_history); |
| 103 | return ipapwd_error_to_kerr(context, ret); |
| 17 | | Calling 'ipapwd_error_to_kerr' | |
|
| 21 | | Returning from 'ipapwd_error_to_kerr' | |
|
| 22 | | Returning zero, which participates in a condition later | |
|
| 104 | } |
| 105 | |
| 106 | krb5_error_code ipadb_change_pwd(krb5_context context, |
| 107 | krb5_keyblock *master_key, |
| 108 | krb5_key_salt_tuple *ks_tuple, |
| 109 | int ks_tuple_count, char *passwd, |
| 110 | int new_kvno, krb5_boolean keepold, |
| 111 | krb5_db_entry *db_entry) |
| 112 | { |
| 113 | krb5_error_code kerr; |
| 114 | krb5_data pwd; |
| |
| 115 | struct ipadb_context *ipactx; |
| 116 | struct ipadb_e_data *ied; |
| 117 | krb5_key_salt_tuple *fks = NULL; |
| 118 | int n_fks; |
| 119 | krb5_key_data *keys = NULL; |
| 120 | int n_keys; |
| 121 | krb5_key_data *tdata; |
| 122 | int t_keys; |
| 123 | int old_kvno; |
| 124 | int ret; |
| 125 | int i; |
| 126 | |
| 127 | ipactx = ipadb_get_context(context); |
| 128 | if (!ipactx) { |
| 2 | | Assuming 'ipactx' is non-null | |
|
| |
| 129 | return KRB5_KDB_DBNOTINITED; |
| 130 | } |
| 131 | |
| 132 | if (!db_entry->e_data) { |
| 4 | | Assuming field 'e_data' is non-null | |
|
| |
| 133 | if (!ipactx->override_restrictions) { |
| 134 | return EINVAL; |
| 135 | } else { |
| 136 | |
| 137 | ied = calloc(1, sizeof(struct ipadb_e_data)); |
| 138 | if (!ied) { |
| 139 | return ENOMEM; |
| 140 | } |
| 141 | ied->magic = IPA_E_DATA_MAGIC; |
| 142 | |
| 143 | ret = asprintf(&ied->pw_policy_dn, |
| 144 | "cn=global_policy,%s", ipactx->realm_base); |
| 145 | if (ret == -1) { |
| 146 | free(ied); |
| 147 | return ENOMEM; |
| 148 | } |
| 149 | db_entry->e_data = (krb5_octet *)ied; |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | |
| 154 | kerr = ipadb_check_pw_policy(context, passwd, db_entry); |
| 6 | | Calling 'ipadb_check_pw_policy' | |
|
| 23 | | Returning from 'ipadb_check_pw_policy' | |
|
| 155 | if (kerr) { |
| |
| 156 | return kerr; |
| 157 | } |
| 158 | |
| 159 | old_kvno = krb5_db_get_key_data_kvno(context, db_entry->n_key_data, |
| 160 | db_entry->key_data); |
| 161 | if (old_kvno >= new_kvno) { |
| 25 | | Assuming 'old_kvno' is < 'new_kvno' | |
|
| |
| 162 | new_kvno = old_kvno + 1; |
| 163 | } |
| 164 | |
| 165 | pwd.data = passwd; |
| 166 | pwd.length = strlen(passwd); |
| 167 | |
| 168 | |
| 169 | if (ks_tuple_count == ipactx->n_supp_encs) { |
| 27 | | Assuming 'ks_tuple_count' is not equal to field 'n_supp_encs' | |
|
| |
| 170 | for (i = 0; i < ks_tuple_count; i++) { |
| 171 | if (ks_tuple[i].ks_enctype != ipactx->supp_encs[i].ks_enctype) |
| 172 | break; |
| 173 | if (ks_tuple[i].ks_salttype != ipactx->supp_encs[i].ks_salttype) |
| 174 | break; |
| 175 | } |
| 176 | if (i == ks_tuple_count) { |
| 177 | |
| 178 | |
| 179 | ks_tuple = ipactx->def_encs; |
| 180 | ks_tuple_count = ipactx->n_def_encs; |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | |
| 185 | |
| 186 | kerr = filter_key_salt_tuples(context, ks_tuple, ks_tuple_count, |
| 187 | ipactx->supp_encs, ipactx->n_supp_encs, |
| 188 | &fks, &n_fks); |
| 189 | if (kerr) { |
| |
| |
| 190 | return kerr; |
| 191 | } |
| 192 | |
| 193 | kerr = ipa_krb5_generate_key_data(context, db_entry->princ, |
| 31 | | Passed-by-value struct argument contains uninitialized data (e.g., field: 'magic') |
|
| 194 | pwd, new_kvno, master_key, |
| 195 | n_fks, fks, &n_keys, &keys); |
| 196 | free(fks); |
| 197 | if (kerr) { |
| 198 | return kerr; |
| 199 | } |
| 200 | |
| 201 | if (keepold) { |
| 202 | |
| 203 | t_keys = db_entry->n_key_data; |
| 204 | |
| 205 | tdata = realloc(db_entry->key_data, |
| 206 | sizeof(krb5_key_data) * (t_keys + n_keys)); |
| 207 | if (!tdata) { |
| 208 | ipa_krb5_free_key_data(keys, n_keys); |
| 209 | return ENOMEM; |
| 210 | } |
| 211 | db_entry->key_data = tdata; |
| 212 | db_entry->n_key_data = t_keys + n_keys; |
| 213 | |
| 214 | for (i = 0; i < n_keys; i++) { |
| 215 | db_entry->key_data[t_keys + i] = keys[i]; |
| 216 | } |
| 217 | free(keys); |
| 218 | |
| 219 | } else { |
| 220 | |
| 221 | ipa_krb5_free_key_data(db_entry->key_data, db_entry->n_key_data); |
| 222 | db_entry->key_data = keys; |
| 223 | db_entry->n_key_data = n_keys; |
| 224 | } |
| 225 | |
| 226 | return 0; |
| 227 | } |
| 228 | |
| 229 | |
| 230 | |
| 231 | |
| 232 | |
| 233 | krb5_error_code ipadb_get_pwd_expiration(krb5_context context, |
| 234 | krb5_db_entry *entry, |
| 235 | struct ipadb_e_data *ied, |
| 236 | time_t *expire_time) |
| 237 | { |
| 238 | krb5_error_code kerr; |
| 239 | krb5_timestamp mod_time = 0; |
| 240 | krb5_principal mod_princ = NULL; |
| 241 | krb5_boolean truexp = true; |
| 242 | |
| 243 | if (ied->ipa_user) { |
| 244 | kerr = krb5_dbe_lookup_mod_princ_data(context, entry, |
| 245 | &mod_time, &mod_princ); |
| 246 | if (kerr) { |
| 247 | goto done; |
| 248 | } |
| 249 | |
| 250 | |
| 251 | |
| 252 | |
| 253 | |
| 254 | if (mod_princ->length == 1 && |
| 255 | strcmp(mod_princ->data[0].data, "kadmind") != 0) { |
| 256 | truexp = krb5_principal_compare(context, mod_princ, entry->princ); |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | if (truexp) { |
| 261 | if (ied->pol) { |
| 262 | if (ied->pol->max_pwd_life) { |
| 263 | *expire_time = mod_time + ied->pol->max_pwd_life; |
| 264 | } else { |
| 265 | *expire_time = 0; |
| 266 | } |
| 267 | } else { |
| 268 | *expire_time = mod_time + IPAPWD_DEFAULT_PWDLIFE; |
| 269 | } |
| 270 | } else { |
| 271 | |
| 272 | *expire_time = mod_time; |
| 273 | } |
| 274 | |
| 275 | |
| 276 | if ((*expire_time) < 0 || (*expire_time) > IPAPWD_END_OF_TIME) { |
| 277 | *expire_time = IPAPWD_END_OF_TIME; |
| 278 | } |
| 279 | |
| 280 | kerr = 0; |
| 281 | |
| 282 | done: |
| 283 | krb5_free_principal(context, mod_princ); |
| 284 | return kerr; |
| 285 | } |