static GArray* inf_adopted_session_get_xml_user_props(InfSession* session, InfXmlConnection* conn, const xmlNodePtr xml) { GArray* array; GParameter* parameter; InfAdoptedStateVector* vector; xmlChar* time; array = INF_SESSION_CLASS(parent_class)->get_xml_user_props( session, conn, xml ); /* Vector time */ time = inf_xml_util_get_attribute(xml, "time"); if(time != NULL) { vector = inf_adopted_state_vector_from_string((const gchar*)time, NULL); xmlFree(time); /* TODO: Error reporting for get_xml_user_props */ if(vector != NULL) { parameter = inf_session_get_user_property(array, "vector"); g_value_init(¶meter->value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_take_boxed(¶meter->value, vector); } } /* log-begin is not in the spec */ #if 0 /* Initial request log, only if ID is also given */ id_param = inf_session_lookup_user_property( (const GParameter*)array->data, array->len, "id" ); if(id_param != NULL && inf_xml_util_get_attribute_uint(xml, "log-begin", &log_begin, NULL)) { log = inf_adopted_request_log_new( g_value_get_uint(&id_param->value), log_begin ); parameter = inf_session_get_user_property(array, "request-log"); g_value_init(¶meter->value, INF_ADOPTED_TYPE_REQUEST_LOG); g_value_take_object(¶meter->value, log); } #endif return array; }
/** * infd_acl_account_info_from_xml: * @xml: The XML node from which to read the account information. * @error: Location to store error information, if any. * * Reads information for one account from a serialized XML node. The account * info can be written to XML with the infd_acl_account_info_to_xml() * function. If the function fails it returns %NULL and @error is set. * * Returns: A #InfdAclAccountInfo, or %NULL. Free with * infd_acl_account_info_free() when no longer needed. */ InfdAclAccountInfo* infd_acl_account_info_from_xml(xmlNodePtr xml, GError** error) { InfdAclAccountInfo* info; InfAclAccount* account; GError* local_error; gboolean has_first_seen; gdouble first_seen; gboolean has_last_seen; gdouble last_seen; xmlChar* password_salt; xmlChar* password_hash; gnutls_datum_t datum; size_t hash_len; int res; gchar* binary_salt; gchar* binary_hash; xmlNodePtr child; GPtrArray* certificate_array; guint i; g_return_val_if_fail(xml != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); local_error = NULL; has_first_seen = inf_xml_util_get_attribute_double( xml, "first-seen", &first_seen, &local_error ); if(local_error != NULL) return NULL; has_last_seen = inf_xml_util_get_attribute_double( xml, "last-seen", &last_seen, &local_error ); if(local_error != NULL) return NULL; account = inf_acl_account_from_xml(xml, error); if(account == NULL) return NULL; password_salt = inf_xml_util_get_attribute(xml, "password-salt"); password_hash = inf_xml_util_get_attribute(xml, "password-hash"); if( (password_salt != NULL && password_hash == NULL) || (password_salt == NULL && password_hash != NULL)) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, "%s", _("If one of \"password-hash\" or \"password-salt\" is provided, the " "other must be provided as well.") ); if(password_salt != NULL) xmlFree(password_salt); if(password_hash != NULL) xmlFree(password_hash); inf_acl_account_free(account); return NULL; } if(password_salt != NULL && password_hash != NULL) { datum.data = password_salt; datum.size = strlen(password_salt); hash_len = 32; binary_salt = g_malloc(hash_len); res = gnutls_hex_decode(&datum, binary_salt, &hash_len); xmlFree(password_salt); if(hash_len != 32) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, "%s", _("The length of the password salt is incorrect, it should " "be 32 bytes") ); xmlFree(password_hash); g_free(binary_salt); return NULL; } else if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); xmlFree(password_hash); g_free(binary_salt); return NULL; } datum.data = password_hash; datum.size = strlen(password_hash); hash_len = gnutls_hash_get_len(GNUTLS_DIG_SHA256); binary_hash = g_malloc(hash_len); res = gnutls_hex_decode(&datum, binary_hash, &hash_len); xmlFree(password_hash); if(hash_len != gnutls_hash_get_len(GNUTLS_DIG_SHA256)) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, _("The length of the password hash is incorrect, it should be " "%u bytes"), (unsigned int)gnutls_hash_get_len(GNUTLS_DIG_SHA256) ); g_free(binary_salt); g_free(binary_hash); return NULL; } else if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); g_free(binary_salt); g_free(binary_hash); return NULL; } } else { binary_salt = NULL; binary_hash = NULL;\ if(password_salt != NULL) xmlFree(password_salt); if(password_hash != NULL) xmlFree(password_hash); } certificate_array = g_ptr_array_new(); for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "certificate") == 0) g_ptr_array_add(certificate_array, xmlNodeGetContent(child)); } info = infd_acl_account_info_new(account->id, account->name, FALSE); inf_acl_account_free(account); info->certificates = g_malloc(sizeof(gchar*) * certificate_array->len); for(i = 0; i < certificate_array->len; ++i) { info->certificates[i] = g_strdup(certificate_array->pdata[i]); xmlFree(certificate_array->pdata[i]); } info->n_certificates = certificate_array->len; g_ptr_array_free(certificate_array, TRUE); info->password_salt = binary_salt; info->password_hash = binary_hash; if(has_first_seen == TRUE) info->first_seen = first_seen * 1e6; else info->first_seen = 0; if(has_last_seen == TRUE) info->last_seen = last_seen * 1e6; else info->last_seen = 0; return info; }