Thread: [PATCH] Pull general SASL framework out of SCRAM
(This is split off from my work on OAUTHBEARER [1].) Currently, the SASL logic is tightly coupled to the SCRAM implementation. This patch untangles the two, by introducing callback structs for both the frontend and backend. In the original thread, Michael Paquier commented: > + /* TODO: SASL_EXCHANGE_FAILURE with output is forbidden in SASL */ > if (result == SASL_EXCHANGE_SUCCESS) > sendAuthRequest(port, > AUTH_REQ_SASL_FIN, > output, > outputlen); > Perhaps that's an issue we need to worry on its own? I didn't recall > this part.. Yeah, it was non-obvious to me on the first read too. It's a consequence of a couple parts of the SASL spec [2]: > The protocol may include an optional additional data field in this > outcome message. This field can only include additional data when > the outcome is successful. and > SASL mechanism specifications MUST supply the following information: > > [...] > > b) An indication of whether the server is expected to provide > additional data when indicating a successful outcome. If so, > if the server sends the additional data as a challenge, the > specification MUST indicate that the response to this challenge > is an empty response. There isn't a corresponding provision for data for a *failed* outcome, so any such data would have to be sent as a separate, mechanism- specific, challenge. This is what OAUTHBEARER has to do, with an annoying "failure handshake". (Note that our protocol implementation provides an "additional data" field for the initial client response, but *not* for the authentication outcome. That seems odd to me, but it is what it is, I suppose.) Regarding that specific TODO -- I think it'd be good for the framework to fail hard if a mechanism tries to send data during a failure outcome, as it probably means the mechanism isn't implemented to spec. --Jacob [1] https://www.postgresql.org/message-id/d1b467a78e0e36ed85a09adf979d04cf124a9d4b.camel@vmware.com [2] https://datatracker.ietf.org/doc/html/rfc4422
Attachment
On Tue, Jun 22, 2021 at 10:37:29PM +0000, Jacob Champion wrote: > Currently, the SASL logic is tightly coupled to the SCRAM > implementation. This patch untangles the two, by introducing callback > structs for both the frontend and backend. The approach to define and have a set callbacks feels natural. +/* Status codes for message exchange */ +#define SASL_EXCHANGE_CONTINUE 0 +#define SASL_EXCHANGE_SUCCESS 1 +#define SASL_EXCHANGE_FAILURE 2 It may be better to prefix those with PG_ as they begin to be published. +/* Backend mechanism API */ +typedef void (*pg_be_sasl_mechanism_func)(Port *, StringInfo); +typedef void *(*pg_be_sasl_init_func)(Port *, const char *, const char *); +typedef int (*pg_be_sasl_exchange_func)(void *, const char *, int, char **, int *, char **); + +typedef struct +{ + pg_be_sasl_mechanism_func get_mechanisms; + pg_be_sasl_init_func init; + pg_be_sasl_exchange_func exchange; +} pg_be_sasl_mech; All this is going to require much more documentation to explain what is the role of those callbacks and what they are here for. Another thing that is not tackled by this patch is the format of the messages exchanged which is something only in SCRAM now. Perhaps it would be better to extract the small-ish routines currently in fe-auth-scram.c and auth-scram.c that we use to grab values associated to an attribute in an exchange message and put them in a central place like an auth-sasl.c and fe-auth-sasl.c. This move could also make sense for the exising init and continue routines for SASL in fe-auth.c. +static int +CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail) +{ + return SASL_exchange(&pg_be_scram_mech, port, shadow_pass, logdetail); +} It may be cleaner to live without this thin wrapper. It is a bit strange to have a SCRAM API in a file where we want mostly SASL things (Okay, uaScram does not count as this is assigned after the HBA lookup). Moving any SASL-related things into a separate file may be a cleaner option, especially considering that we have a bit more than the exchange itself, like message handling. +typedef void *(*pg_sasl_init_func)(PGconn *, const char *, const char *); +typedef void (*pg_sasl_exchange_func)(void *, char *, int, char **, int *, bool *, bool *); +typedef bool (*pg_sasl_channel_bound_func)(void *); +typedef void (*pg_sasl_free_func)(void *); + +typedef struct +{ + pg_sasl_init_func init; + pg_sasl_exchange_func exchange; + pg_sasl_channel_bound_func channel_bound; + pg_sasl_free_func free; +} pg_sasl_mech; These would be better into a separate header, with more documentation. It may be more consistent with the backend to name that pg_fe_sasl_mech? It looks like there is enough material for a callback able to handle channel binding. In the main patch for OAUTHBEARER, I can see for example that the handling of OAUTHBEARER-PLUS copied from its SCRAM sibling. That does not need to be tackled in the same patch. Just noting it on the way. > (Note that our protocol implementation provides an "additional data" > field for the initial client response, but *not* for the authentication > outcome. That seems odd to me, but it is what it is, I suppose.) You are referring to the protocol implementation as of AuthenticationSASLFinal, right? > Regarding that specific TODO -- I think it'd be good for the framework > to fail hard if a mechanism tries to send data during a failure > outcome, as it probably means the mechanism isn't implemented to spec. Agreed. That would mean patching libpq to add more safeguards in pg_SASL_continue() if I am following correctly. -- Michael
Attachment
On Wed, 2021-06-23 at 16:38 +0900, Michael Paquier wrote: > On Tue, Jun 22, 2021 at 10:37:29PM +0000, Jacob Champion wrote: > > Currently, the SASL logic is tightly coupled to the SCRAM > > implementation. This patch untangles the two, by introducing callback > > structs for both the frontend and backend. > > The approach to define and have a set callbacks feels natural. Good, thanks! > +/* Status codes for message exchange */ > +#define SASL_EXCHANGE_CONTINUE 0 > +#define SASL_EXCHANGE_SUCCESS 1 > +#define SASL_EXCHANGE_FAILURE 2 > > It may be better to prefix those with PG_ as they begin to be > published. Added in v2. > +/* Backend mechanism API */ > +typedef void (*pg_be_sasl_mechanism_func)(Port *, StringInfo); > +typedef void *(*pg_be_sasl_init_func)(Port *, const char *, const > char *); > +typedef int (*pg_be_sasl_exchange_func)(void *, const char *, int, > char **, int *, char **); > + > +typedef struct > +{ > + pg_be_sasl_mechanism_func get_mechanisms; > + pg_be_sasl_init_func init; > + pg_be_sasl_exchange_func exchange; > +} pg_be_sasl_mech; > > All this is going to require much more documentation to explain what > is the role of those callbacks and what they are here for. Yes, definitely. If the current approach seems generally workable, I'll get started on that. > Another thing that is not tackled by this patch is the format of the > messages exchanged which is something only in SCRAM now. Perhaps it > would be better to extract the small-ish routines currently in > fe-auth-scram.c and auth-scram.c that we use to grab values associated > to an attribute in an exchange message and put them in a central place > like an auth-sasl.c and fe-auth-sasl.c. This move could also make > sense for the exising init and continue routines for SASL in > fe-auth.c. We can. I recommend waiting for another GS2 mechanism implementation, though. The attribute/value encoding is not part of core SASL (see [1] for that RFC), and OAUTHBEARER is not technically a GS2 mechanism -- though it makes use of a vestigal GS2 header block, apparently in the hopes that one day it might become one. So we could pull out the similarities now, but I'd hate to extract the wrong abstractions and make someone else untangle it later. > +static int > +CheckSCRAMAuth(Port *port, char *shadow_pass, char **logdetail) > +{ > + return SASL_exchange(&pg_be_scram_mech, port, shadow_pass, logdetail); > +} > It may be cleaner to live without this thin wrapper. It is a bit > strange to have a SCRAM API in a file where we want mostly SASL things > (Okay, uaScram does not count as this is assigned after the HBA > lookup). Moving any SASL-related things into a separate file may be a > cleaner option, especially considering that we have a bit more than > the exchange itself, like message handling. Heh, I figured that at ~3500 lines, you all just really wanted the Check* implementations to live in auth.c. :D I can definitely move it (into, say, auth-sasl.c?). I'll probably do that in a second commit, though, since keeping it in place during the refactor makes the review easier IMO. > +typedef void *(*pg_sasl_init_func)(PGconn *, const char *, const char > *); > +typedef void (*pg_sasl_exchange_func)(void *, char *, int, char **, > int *, bool *, bool *); > +typedef bool (*pg_sasl_channel_bound_func)(void *); > +typedef void (*pg_sasl_free_func)(void *); > + > +typedef struct > +{ > + pg_sasl_init_func init; > + pg_sasl_exchange_func exchange; > + pg_sasl_channel_bound_func channel_bound; > + pg_sasl_free_func free; > +} pg_sasl_mech; > These would be better into a separate header, with more > documentation. Can do. Does libpq-int-sasl.h work as a filename? This should not be exported to applications. > It may be more consistent with the backend to name > that pg_fe_sasl_mech? Done in v2. > It looks like there is enough material for a callback able to handle > channel binding. In the main patch for OAUTHBEARER, I can see for > example that the handling of OAUTHBEARER-PLUS copied from its SCRAM > sibling. That does not need to be tackled in the same patch. Just > noting it on the way. OAUTHBEARER doesn't support channel binding -- there's no OAUTHBEARER- PLUS, and there probably won't ever be, given the mechanism's simplicity -- so I'd recommend that this wait for a second GS2 mechanism implementation, as well. > > (Note that our protocol implementation provides an "additional data" > > field for the initial client response, but *not* for the authentication > > outcome. That seems odd to me, but it is what it is, I suppose.) > > You are referring to the protocol implementation as of > AuthenticationSASLFinal, right? Yes, but I misremembered. My statement was wrong -- we do allow for additional data in the authentication outcome from the server. For AuthenticationSASLFinal, we don't distinguish between "no additional data" and "additional data of length zero", which IIRC is a violation of the SASL protocol. That may cause problems with a theoretical future mechanism implementation, but I don't think it affects SCRAM. I believe we *do* distinguish between those cases correctly for the initial client response packet. Sorry for the confusion; let me double-check again when I have fresh eyes at the start of the week, before sending you on a goose chase. > > Regarding that specific TODO -- I think it'd be good for the framework > > to fail hard if a mechanism tries to send data during a failure > > outcome, as it probably means the mechanism isn't implemented to spec. > > Agreed. That would mean patching libpq to add more safeguards in > pg_SASL_continue() if I am following correctly. Right. Thanks for the review! --Jacob [1] https://datatracker.ietf.org/doc/html/rfc5801
Attachment
On Fri, Jun 25, 2021 at 11:40:33PM +0000, Jacob Champion wrote: > I can definitely move it (into, say, auth-sasl.c?). I'll probably do > that in a second commit, though, since keeping it in place during the > refactor makes the review easier IMO. auth-sasl.c is a name consistent with the existing practice. > Can do. Does libpq-int-sasl.h work as a filename? This should not be > exported to applications. I would still with the existing naming used by fe-gssapi-common.h, so that would be fe-auth-sasl.c and fe-auth-sasl.h, with the header remaining internal. Not strongly wedded to this name, of course, that just seems consistent. -- Michael
Attachment
On Sat, 2021-06-26 at 09:47 +0900, Michael Paquier wrote: > On Fri, Jun 25, 2021 at 11:40:33PM +0000, Jacob Champion wrote: > > I can definitely move it (into, say, auth-sasl.c?). I'll probably do > > that in a second commit, though, since keeping it in place during the > > refactor makes the review easier IMO. > > auth-sasl.c is a name consistent with the existing practice. > > > Can do. Does libpq-int-sasl.h work as a filename? This should not be > > exported to applications. > > I would still with the existing naming used by fe-gssapi-common.h, so > that would be fe-auth-sasl.c and fe-auth-sasl.h, with the header > remaining internal. Not strongly wedded to this name, of course, that > just seems consistent. Done in v3, with a second patch for the code motion. I added a first pass at API documentation as well. This exposed some additional front-end TODOs that I added inline, but they should probably be dealt with independently of the refactor: - Zero-length client responses are legal in the SASL framework; currently we use zero as a sentinel for "don't send a response". - I don't think it's legal for a client to refuse a challenge from the server without aborting the exchange, so we should probably check to make sure that client responses are non-NULL in the success case. --Jacob
Attachment
On Wed, Jun 30, 2021 at 10:30:12PM +0000, Jacob Champion wrote: > Done in v3, with a second patch for the code motion. I have gone through that, tweaking the documentation you have added as that's the meat of the patch, reworking a bit the declarations of the callbacks (no need for several typedef gere) and doing some small format changes to make the indentation happy. And that looks pretty good. It is a bit sad that the SCRAM part cannot be completely unplugged from the auth part, because of the call to the free function and the HBA checks, but adding more wrappers to accomodate with that is not really worth it. So I'd like to apply that to clarify this code layer, without the TODOs. - pg_be_scram_get_mechanisms(port, &sasl_mechs); - /* Put another '\0' to mark that list is finished. */ - appendStringInfoChar(&sasl_mechs, '\0'); I was wondering for a couple of seconds if it would not be better to let the last '\0' being set within the callback, but what you have here looks better. - if (!pg_fe_scram_channel_bound(conn->sasl_state)) + if (!conn->sasl || !conn->sasl->channel_bound(conn->sasl_state)) conn->sasl should be set in this code path. This style is safer. The top comment of scram_init() still mentioned pg_be_scram_get_mechanisms(), while it should be scram_get_mechanisms(). PG_MAX_SASL_MESSAGE_LENGTH can stay within auth-sasl.c. > I added a first pass at API documentation as well. This exposed some > additional front-end TODOs that I added inline, but they should > probably be dealt with independently of the refactor: > > - Zero-length client responses are legal in the SASL framework; > currently we use zero as a sentinel for "don't send a response". Check. > - I don't think it's legal for a client to refuse a challenge from the > server without aborting the exchange, so we should probably check to > make sure that client responses are non-NULL in the success case. Hmm. Does the RFCs tell us anything about that? -- Michael
Attachment
On Mon, 2021-07-05 at 17:17 +0900, Michael Paquier wrote: > On Wed, Jun 30, 2021 at 10:30:12PM +0000, Jacob Champion wrote: > > Done in v3, with a second patch for the code motion. > > I have gone through that, tweaking the documentation you have added as > that's the meat of the patch, reworking a bit the declarations of the > callbacks (no need for several typedef gere) and doing some small > format changes to make the indentation happy. And that looks pretty > good. Looks very good, thanks! A few comments on the docs changes: > + * Output parameters: > + * > + * buf: A StringInfo buffer that the callback should populate with > + * supported mechanism names. The names are appended into this > + * StringInfo, separated by '\0' bytes. Each name must be null-terminated, not just null-separated. That way the list of names ends with an empty string: name-one\0 <- added by the mechanism name-two\0 <- added by the mechanism \0 <- added by the framework The way it's worded now, I could see some implementers failing to terminate the final name because the framework adds a trailing null already -- but the framework is terminating the list, not the final name. > + * init() > + * > + * Initializes mechanism-specific state for a connection. This > + * callback must return a pointer to its allocated state, which will > + * be passed as-is as the first argument to the other callbacks. > + * free() is called to release any state resources. Maybe say "The free() callback is called" to differentiate it from standard free()? > It is a bit sad that the SCRAM part cannot be completely > unplugged from the auth part, because of the call to the free function > and the HBA checks, but adding more wrappers to accomodate with that > is not really worth it. Yeah. I think that additional improvements/refactoring here will come naturally if clients are ever allowed to negotiate SASL mechanisms in the future. Doesn't need to happen now. > - if (!pg_fe_scram_channel_bound(conn->sasl_state)) > + if (!conn->sasl || !conn->sasl->channel_bound(conn->sasl_state)) > conn->sasl should be set in this code path. This style is safer. It's possible for conn->sasl to be NULL here, say if the client has channel_binding=require but connects as a user with an MD5 secret. The SCRAM TAP tests have one such case. > The top comment of scram_init() still mentioned > pg_be_scram_get_mechanisms(), while it should be > scram_get_mechanisms(). > > PG_MAX_SASL_MESSAGE_LENGTH can stay within auth-sasl.c. Looks good to me. > > - I don't think it's legal for a client to refuse a challenge from the > > server without aborting the exchange, so we should probably check to > > make sure that client responses are non-NULL in the success case. > > Hmm. Does the RFCs tell us anything about that? Just in general terms: > Each authentication exchange consists of a message from the client to > the server requesting authentication via a particular mechanism, > followed by one or more pairs of challenges from the server and > responses from the client, followed by a message from the server > indicating the outcome of the authentication exchange. (Note: > exchanges may also be aborted as discussed in Section 3.5.) So a challenge must be met with a response, or the exchange must be aborted. (And I don't think our protocol implementation provides a client abort message; if something goes wrong, we just tear down the connection.) Thanks, --Jacob
On Tue, Jul 06, 2021 at 06:20:49PM +0000, Jacob Champion wrote: > On Mon, 2021-07-05 at 17:17 +0900, Michael Paquier wrote: > Each name must be null-terminated, not just null-separated. That way > the list of names ends with an empty string: > > name-one\0 <- added by the mechanism > name-two\0 <- added by the mechanism > \0 <- added by the framework > > The way it's worded now, I could see some implementers failing to > terminate the final name because the framework adds a trailing null > already -- but the framework is terminating the list, not the final > name. Good point. I have used ending with '\0' bytes instead. >> + * init() >> + * >> + * Initializes mechanism-specific state for a connection. This >> + * callback must return a pointer to its allocated state, which will >> + * be passed as-is as the first argument to the other callbacks. >> + * free() is called to release any state resources. > > Maybe say "The free() callback is called" to differentiate it from > standard free()? Yes, that could be confusing. Switched to your wording instead. > It's possible for conn->sasl to be NULL here, say if the client has > channel_binding=require but connects as a user with an MD5 secret. The > SCRAM TAP tests have one such case. Indeed. >> Hmm. Does the RFCs tell us anything about that? > > Just in general terms: > >> Each authentication exchange consists of a message from the client to >> the server requesting authentication via a particular mechanism, >> followed by one or more pairs of challenges from the server and >> responses from the client, followed by a message from the server >> indicating the outcome of the authentication exchange. (Note: >> exchanges may also be aborted as discussed in Section 3.5.) > > So a challenge must be met with a response, or the exchange must be > aborted. (And I don't think our protocol implementation provides a > client abort message; if something goes wrong, we just tear down the > connection.) Thanks. At the same time, section 3.5 also says that the client may send a message to abort. So one can interpret that the client has also the choice to abort without sending a response back to the server? Or I am just interpreting incorrectly the use of "may" in this context? -- Michael
Attachment
On Wed, 2021-07-07 at 14:08 +0900, Michael Paquier wrote: > On Tue, Jul 06, 2021 at 06:20:49PM +0000, Jacob Champion wrote: > > On Mon, 2021-07-05 at 17:17 +0900, Michael Paquier wrote: > > > > > Hmm. Does the RFCs tell us anything about that? > > > > Just in general terms: > > > > > Each authentication exchange consists of a message from the client to > > > the server requesting authentication via a particular mechanism, > > > followed by one or more pairs of challenges from the server and > > > responses from the client, followed by a message from the server > > > indicating the outcome of the authentication exchange. (Note: > > > exchanges may also be aborted as discussed in Section 3.5.) > > > > So a challenge must be met with a response, or the exchange must be > > aborted. (And I don't think our protocol implementation provides a > > client abort message; if something goes wrong, we just tear down the > > connection.) > > Thanks. At the same time, section 3.5 also says that the client may > send a message to abort. So one can interpret that the client has > also the choice to abort without sending a response back to the > server? Or I am just interpreting incorrectly the use of "may" in > this context? That's correct. But the client may not simply ignore the challenge and keep the exchange open waiting for a new one, as pg_SASL_continue() currently allows. That's what my TODO is referring to. --Jacob
On Wed, Jul 07, 2021 at 03:07:14PM +0000, Jacob Champion wrote: > That's correct. But the client may not simply ignore the challenge and > keep the exchange open waiting for a new one, as pg_SASL_continue() > currently allows. That's what my TODO is referring to. I have been looking more at your three points from upthread and feasted on the SASL RFC, as of: - Detection that no output is generated on PG_SASL_EXCHANGE_FAILURE for the backend. - Handling of zero-length messages in the frontend. The backend handles that already, and SCRAM would complain if sending such messages, but I can see why you'd want to allow that for other mechanisms. - Making sure that a mechanism generates a message in the middle of the exchange in the frontend. I agree that this looks like an improvement in terms of the expectations behind a SASL mechanism, so I have done the attached to strengthen a bit all those checks. However, I don't really see a point in back-patching any of that, as SCRAM satisfies with its implementation already all those conditions AFAIK. So that's an improvement of the current code, and it fits nicely with the SASL refactoring for the documentation of the callbacks. Thoughts? -- Michael
Attachment
On Thu, 2021-07-08 at 16:27 +0900, Michael Paquier wrote: > I agree that this looks like an improvement in terms of the > expectations behind a SASL mechanism, so I have done the attached to > strengthen a bit all those checks. However, I don't really see a > point in back-patching any of that, as SCRAM satisfies with its > implementation already all those conditions AFAIK. Agreed. > Thoughts? LGTM, thanks! > + * outputlen: The length (0 or higher) of the client response buffer, > + * invalid if output is NULL. nitpick: maybe "ignored" instead of "invalid"? --Jacob
On Fri, Jul 09, 2021 at 11:31:48PM +0000, Jacob Champion wrote: > On Thu, 2021-07-08 at 16:27 +0900, Michael Paquier wrote: >> + * outputlen: The length (0 or higher) of the client response buffer, >> + * invalid if output is NULL. > > nitpick: maybe "ignored" instead of "invalid"? Thanks, applied as 44bd012 after using your suggestion. Another thing I noticed after more review is that the check in fe-auth.c to make sure that a message needs to be generated if the exchange is not completed yet has no need to depend on "success", only "done". -- Michael
Attachment
On Sun, 2021-07-11 at 13:16 +0900, Michael Paquier wrote: > On Fri, Jul 09, 2021 at 11:31:48PM +0000, Jacob Champion wrote: > > On Thu, 2021-07-08 at 16:27 +0900, Michael Paquier wrote: > > > + * outputlen: The length (0 or higher) of the client response buffer, > > > + * invalid if output is NULL. > > > > nitpick: maybe "ignored" instead of "invalid"? > > Thanks, applied as 44bd012 after using your suggestion. Thanks! > Another thing I noticed after more review is that the check in > fe-auth.c to make sure that a message needs to be generated if the > exchange is not completed yet has no need to depend on "success", only > "done". Ah, right. I think the (!done && !success) case is probably indicative of an API smell, but that's probably something to clean up in a future pass. --Jacob
On Tue, Jul 13, 2021 at 12:01:46AM +0000, Jacob Champion wrote: > Ah, right. I think the (!done && !success) case is probably indicative > of an API smell, but that's probably something to clean up in a future > pass. Yeah, agreed. I feel that it would should be cleaner to replace those two booleans with a status enum or a bitmask. -- Michael
Attachment
Hello, hackers! I got an error while building one of the extensions. /home/mkulagin/pg-install/postgresql-master/include/internal/libpq-int.h:44:10: fatal error: fe-auth-sasl.h: No such fileor directory #include "fe-auth-sasl.h" ^~~~~~~~~~~~~~~~ I think the new fe-auth-sasl.h file should be installed too. Correction proposal in the attached file (but I'm not sure that fix of Install.pm is correct). Regards, Mikhail A. Kulagin PostgresPro
Attachment
On Tue, Jul 13, 2021 at 12:41:27PM +0300, Mikhail Kulagin wrote: > I got an error while building one of the extensions. > /home/mkulagin/pg-install/postgresql-master/include/internal/libpq-int.h:44:10: fatal error: fe-auth-sasl.h: No such fileor directory > #include "fe-auth-sasl.h" > ^~~~~~~~~~~~~~~~ Right. I overlooked the fact that libpq-int.h is installed. > I think the new fe-auth-sasl.h file should be installed too. > Correction proposal in the attached file (but I'm not sure that fix > of Install.pm is correct). That looks correct to me. I'll check that tomorrow. -- Michael
Attachment
On Tue, 2021-07-13 at 19:31 +0900, Michael Paquier wrote: > On Tue, Jul 13, 2021 at 12:41:27PM +0300, Mikhail Kulagin wrote: > > I got an error while building one of the extensions. > > /home/mkulagin/pg-install/postgresql-master/include/internal/libpq-int.h:44:10: fatal error: fe-auth-sasl.h: No suchfile or directory > > #include "fe-auth-sasl.h" > > ^~~~~~~~~~~~~~~~ > > Right. I overlooked the fact that libpq-int.h is installed. Thanks for catching that Mikhail. > > I think the new fe-auth-sasl.h file should be installed too. > > Correction proposal in the attached file (but I'm not sure that fix > > of Install.pm is correct). > > That looks correct to me. I'll check that tomorrow. Looks right to me too. I'm currently rebuilding my Windows dev environment so I haven't been able to double-check that piece of it. Just to make sure -- do we want to export the fe-auth-sasl.h header as opposed to forward-declaring the pg_fe_sasl_mech struct? Is the use case for libpq-int.h just "here, have at the internals, and if you break it then it's on you"? --Jacob
On Tue, 2021-07-13 at 22:41 +0000, Jacob Champion wrote: > On Tue, 2021-07-13 at 19:31 +0900, Michael Paquier wrote: > > On Tue, Jul 13, 2021 at 12:41:27PM +0300, Mikhail Kulagin wrote: > > > > > > I think the new fe-auth-sasl.h file should be installed too. > > > Correction proposal in the attached file (but I'm not sure that fix > > > of Install.pm is correct). > > > > That looks correct to me. I'll check that tomorrow. > > Looks right to me too. I'm currently rebuilding my Windows dev > environment so I haven't been able to double-check that piece of it. (Confirmed that this patch works for me on Windows.) Thanks, --Jacob
On Tue, Jul 13, 2021 at 10:41:01PM +0000, Jacob Champion wrote: > Just to make sure -- do we want to export the fe-auth-sasl.h header as > opposed to forward-declaring the pg_fe_sasl_mech struct? Installing fe-auth-sasl.h has the advantage to make the internals of the callbacks available to applications playing with the internals. For SASL, it makes things easier to define new mechanisms out of core. > Is the use > case for libpq-int.h just "here, have at the internals, and if you > break it then it's on you"? Yes, it can be useful for applications willing to use the internals of libpq, like in forks. There is no guarantee that this will not break across major version upgrades, so that's up to the user to fix things once they play with the internals. -- Michael