Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cZdNm-0008EA-S3 for pgsql-hackers@arkaria.postgresql.org; Fri, 03 Feb 2017 12:54:30 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1cZdNm-0000Fr-C0 for pgsql-hackers@arkaria.postgresql.org; Fri, 03 Feb 2017 12:54:30 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1cZdML-00076T-Sc for pgsql-hackers@postgresql.org; Fri, 03 Feb 2017 12:53:02 +0000 Received: from mail-lf0-x241.google.com ([2a00:1450:4010:c07::241]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84_2) (envelope-from ) id 1cZdMH-0003gr-BN for pgsql-hackers@postgresql.org; Fri, 03 Feb 2017 12:53:00 +0000 Received: by mail-lf0-x241.google.com with SMTP id q89so1453317lfi.1 for ; Fri, 03 Feb 2017 04:52:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=KmdEYI76aMiaVFVpIJGWIxt8vaa03Y+H+SbX7/aSRbc=; b=rEq8M3k/i+mhJsdwKUf15oSltRsobxYHBEllaETlTWyZ/NSBw6SIU7NBRznLw99Z0u D3tULH7TTZXOFD+la1VcT8u80LU0eDDxVCxjAU1kIzCAExyVWUqUJ5QolQdO0+PDjgtq TKG3slncu7m4oQyP9rvUOyTedUUFv2Ya0UvSZmrLw0wbrupYub4/52nAs/hVqDLOyYOF APqgVg9665O295kTg8KhDxnvwVodp715OnrX+d7Bv7xBHKkDFUtNUi/W7Bxdz/qddyH0 H3V4bmkK4fddO3SyrzbTPnKZMjHnDJETzDFtUv/8xwTOfpOUScdc0rPwaRQEJ1TLIoQz Lf9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:subject:to:references:cc:from:message-id :date:user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=KmdEYI76aMiaVFVpIJGWIxt8vaa03Y+H+SbX7/aSRbc=; b=PI4Mje/S/mAuytAMLiu8sIPJK/lKQnmZoSZrY95AJ07OmI8hpM3ylzcj0V8a4foALy YxIx2cUhJYNLBI48IURKD9CgZP/HoT+9K5TjAox/p1CjJIOPsjJqQoAEwHpLtE9EfC4X oGEVYwso6+NDORv4vQ65LPBH92CRhp+IIpHqFKNfgNXipyxwCmj4fYLzrWYp3MpPWSIN /qmu5jHNzRZeoFa1hS/dgCjYZDQPfz9DYv3qGAr3UYXOAFePM1kavZsMIs7eFkVBBdW/ gU8LDCTRsQ2BC5J2HgLfRT7beJj5eNTuaTiPh9H2wQzs3pZoHbyDYOvG5qz0NTZcdpZR T4pg== X-Gm-Message-State: AIkVDXJlJY58vR7ItfWVWdvfPwFbpEjMObnSHylJcnftPxHxEjkk/u6MbhqfiDoanF3FQw== X-Received: by 10.25.17.198 with SMTP id 67mr4835455lfr.39.1486126375096; Fri, 03 Feb 2017 04:52:55 -0800 (PST) Received: from [192.168.1.112] (dsl-hkibrasgw1-50df7f-241.dhcp.inet.fi. [80.223.127.241]) by smtp.gmail.com with ESMTPSA id 70sm7599185lfw.11.2017.02.03.04.52.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Feb 2017 04:52:54 -0800 (PST) Subject: Re: Password identifiers, protocol aging and SCRAM protocol To: Michael Paquier References: <21eecdb8-365b-8347-1ae2-5278d1fe798c@iki.fi> <3029e460-d47c-710e-507e-d8ba759d7cbb@iki.fi> <20161209111041.GA23215@paquier.xyz> <973937ca-cbed-ad48-c783-e29723a2a9c0@iki.fi> Cc: Robert Haas , Andres Freund , Peter Eisentraut , David Steele , Tom Lane , David Fetter , Alvaro Herrera , Magnus Hagander , Julian Markwort , Stephen Frost , PostgreSQL mailing lists , Valery Popov From: Heikki Linnakangas Message-ID: Date: Fri, 3 Feb 2017 14:52:52 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.6.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Pg-Spam-Score: -2.6 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org On 12/20/2016 03:47 AM, Michael Paquier wrote: > The first thing is to be able to understand in the SCRAM code if a > string is UTF-8 or not, and this code is in src/common/. pg_wchar.c > offers a set of routines exactly for this purpose, which is built with > libpq but that's not available for src/common/. So instead of moving > all the file, I'd like to create a new file in src/common/utf8.c which > includes pg_utf_mblen() and pg_utf8_islegal(). Sounds reasonable. They're short functions, might also be ok to just copy-paste them to scram-common.c. > On top of that I think that having a routine able to check a full > string would be useful for many users, as pg_utf8_islegal() can only > check one set of characters. If the password string is found to be of > UTF-8 format, SASLprepare is applied. If not, the string is copied > as-is with perhaps unexpected effects for the client But he's in > trouble already if client is not using UTF-8. Yeah. > The second thing is the normalization itself. Per RFC4013, NFKC needs > to be applied to the string. The operation is described in [1] > completely, and it is named as doing 1) a compatibility decomposition > of the bytes of the string, followed by 2) a canonical composition. > > About 1). The compatibility decomposition is defined in [2], "by > recursively applying the canonical and compatibility mappings, then > applying the canonical reordering algorithm". Canonical and > compatibility mapping are some data available in UnicodeData.txt, the > 6th column of the set defined in [3] to be precise. The meaning of the > decomposition mappings is defined in [2] as well. The canonical > decomposition is basically to look for a given UTF-8 character, and > then apply the multiple characters resulting in its new shape. The > compatibility mapping should as well be applied, but [5], a perl tool > called charlint.pl doing this normalization work, does not care about > this phase... Do we? Not sure. We need to do whatever the "right thing" is, according to the RFC. I would assume that the spec is not ambiguous this, but I haven't looked into the details. If it's ambiguous, then I think we need to look at some popular implementations to see what they do. > About 2)... Once the decomposition has been applied, those bytes need > to be recomposed using the Canonical_Combining_Class field of > UnicodeData.txt in [3], which is the 3rd column of the set. Its values > are defined in [4]. An other interesting thing, charlint.pl [5] does > not care about this phase. I am wondering if we should as well not > just drop this part as well... > > Once 1) and 2) are done, NKFC is complete, and so is SASLPrepare. Ok. > So what we need from Postgres side is a mapping table to, having the > following fields: > 1) Hexa sequence of UTF8 character. > 2) Its canonical combining class. > 3) The kind of decomposition mapping if defined. > 4) The decomposition mapping, in hexadecimal format. > Based on what I looked at, either perl or python could be used to > process UnicodeData.txt and to generate a header file that would be > included in the tree. There are 30k entries in UnicodeData.txt, 5k of > them have a mapping, so that will result in many tables. One thing to > improve performance would be to store the length of the table in a > static variable, order the entries by their hexadecimal keys and do a > dichotomy lookup to find an entry. We could as well use more fancy > things like a set of tables using a Radix tree using decomposed by > bytes. We should finish by just doing one lookup of the table for each > character sets anyway. Ok. I'm not too worried about the performance of this. It's only used for passwords, which are not that long, and it's only done when connecting. I'm more worried about the disk/memory usage. How small can we pack the tables? 10kB? 100kB? Even a few MB would probably not be too bad in practice, but I'd hate to bloat up libpq just for this. > In conclusion, at this point I am looking for feedback regarding the > following items: > 1) Where to put the UTF8 check routines and what to move. Covered that above. > 2) How to generate the mapping table using UnicodeData.txt. I'd think > that using perl would be better. Agreed, it needs to be in Perl. That's what we require to be present when building PostgreSQL, it's what we use for generating other tables and functions. > 3) The shape of the mapping table, which depends on how many > operations we want to support in the normalization of the strings. > The decisions for those items will drive the implementation in one > sense or another. Let's aim for small disk/memory footprint. - Heikki > [1]: http://www.unicode.org/reports/tr15/#Description_Norm > [2]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#Character_Decomposition_Mappings > [3]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#UnicodeData.txt > [4]: http://www.unicode.org/Public/5.1.0/ucd/UCD.html#Canonical_Combining_Class_Values > [5]: https://www.w3.org/International/charlint/ -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers