int _gnutls_srp_pwd_read_entry (gnutls_session_t state, char *username, SRP_PWD_ENTRY ** _entry) { gnutls_srp_server_credentials_t cred; FILE *fd; char line[2 * 1024]; unsigned i, len; int ret; int idx, last_idx; SRP_PWD_ENTRY *entry; *_entry = gnutls_calloc (1, sizeof (SRP_PWD_ENTRY)); if (*_entry == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } entry = *_entry; cred = (gnutls_srp_server_credentials_t) _gnutls_get_cred (state->key, GNUTLS_CRD_SRP, NULL); if (cred == NULL) { gnutls_assert (); _gnutls_srp_entry_free (entry); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } /* if the callback which sends the parameters is * set, use it. */ if (cred->pwd_callback != NULL) { ret = cred->pwd_callback (state, username, &entry->salt, &entry->v, &entry->g, &entry->n); if (ret == 1) { /* the user does not exist */ if (entry->g.size != 0 && entry->n.size != 0) { ret = _randomize_pwd_entry (entry); if (ret < 0) { gnutls_assert (); _gnutls_srp_entry_free (entry); return ret; } return 0; } else { gnutls_assert (); ret = -1; /* error in the callback */ } } if (ret < 0) { gnutls_assert (); _gnutls_srp_entry_free (entry); return GNUTLS_E_SRP_PWD_ERROR; } return 0; } /* The callback was not set. Proceed. */ if (cred->password_file == NULL) { gnutls_assert (); return GNUTLS_E_SRP_PWD_ERROR; } /* Open the selected password file. */ fd = fopen (cred->password_file, "r"); if (fd == NULL) { gnutls_assert (); _gnutls_srp_entry_free (entry); return GNUTLS_E_SRP_PWD_ERROR; } last_idx = 1; /* a default value */ len = strlen (username); while (fgets (line, sizeof (line), fd) != NULL) { /* move to first ':' */ i = 0; while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line))) { i++; } if (strncmp (username, line, MAX (i, len)) == 0) { if ((idx = pwd_put_values (entry, line)) >= 0) { /* Keep the last index in memory, so we can retrieve fake parameters (g,n) * when the user does not exist. */ /* XXX: last_idx will not be read as both if block branches return. */ last_idx = idx; if (pwd_read_conf (cred->password_conf_file, entry, idx) == 0) { return 0; } else { gnutls_assert (); _gnutls_srp_entry_free (entry); return GNUTLS_E_SRP_PWD_ERROR; } } else { gnutls_assert (); _gnutls_srp_entry_free (entry); return GNUTLS_E_SRP_PWD_ERROR; } } } /* user was not found. Fake him. Actually read the g,n values from * the last index found and randomize the entry. */ if (pwd_read_conf (cred->password_conf_file, entry, last_idx) == 0) { ret = _randomize_pwd_entry (entry); if (ret < 0) { gnutls_assert (); _gnutls_srp_entry_free (entry); return ret; } return 0; } gnutls_assert (); _gnutls_srp_entry_free (entry); return GNUTLS_E_SRP_PWD_ERROR; }
int _gnutls_srp_pwd_read_entry(gnutls_session_t state, char *username, SRP_PWD_ENTRY ** _entry) { gnutls_srp_server_credentials_t cred; FILE *fd = NULL; char *line = NULL; size_t line_size = 0; unsigned i, len; int ret; int idx; SRP_PWD_ENTRY *entry = NULL; *_entry = gnutls_calloc(1, sizeof(SRP_PWD_ENTRY)); if (*_entry == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } entry = *_entry; cred = (gnutls_srp_server_credentials_t) _gnutls_get_cred(state, GNUTLS_CRD_SRP); if (cred == NULL) { gnutls_assert(); ret = GNUTLS_E_INSUFFICIENT_CREDENTIALS; goto cleanup; } /* if the callback which sends the parameters is * set, use it. */ if (cred->pwd_callback != NULL) { ret = cred->pwd_callback(state, username, &entry->salt, &entry->v, &entry->g, &entry->n); if (ret == 1) { /* the user does not exist */ if (entry->g.size != 0 && entry->n.size != 0) { ret = _randomize_pwd_entry(entry, cred, username); if (ret < 0) { gnutls_assert(); goto cleanup; } return 0; } else { gnutls_assert(); ret = -1; /* error in the callback */ } } if (ret < 0) { gnutls_assert(); ret = GNUTLS_E_SRP_PWD_ERROR; goto cleanup; } return 0; } /* The callback was not set. Proceed. */ if (cred->password_file == NULL) { gnutls_assert(); ret = GNUTLS_E_SRP_PWD_ERROR; goto cleanup; } /* Open the selected password file. */ fd = fopen(cred->password_file, "r"); if (fd == NULL) { gnutls_assert(); ret = GNUTLS_E_SRP_PWD_ERROR; goto cleanup; } len = strlen(username); while (getline(&line, &line_size, fd) > 0) { /* move to first ':' */ i = 0; while ((i < line_size) && (line[i] != '\0') && (line[i] != ':')) { i++; } if (strncmp(username, line, MAX(i, len)) == 0) { if ((idx = parse_tpasswd_values(entry, line)) >= 0) { /* Keep the last index in memory, so we can retrieve fake parameters (g,n) * when the user does not exist. */ if (pwd_read_conf (cred->password_conf_file, entry, idx) == 0) { ret = 0; goto found; } else { gnutls_assert(); ret = GNUTLS_E_SRP_PWD_ERROR; goto cleanup; } } else { gnutls_assert(); ret = GNUTLS_E_SRP_PWD_ERROR; goto cleanup; } } } /* user was not found. Fake him. Actually read the g,n values from * the last index found and randomize the entry. */ if (pwd_read_conf(cred->password_conf_file, entry, 1) == 0) { ret = _randomize_pwd_entry(entry, cred, username); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; goto found; } ret = GNUTLS_E_SRP_PWD_ERROR; cleanup: gnutls_assert(); _gnutls_srp_entry_free(entry); found: zeroize_key(line, line_size); free(line); if (fd) fclose(fd); return ret; }