since-v12.diff.txt

text/plain

Filename: since-v12.diff.txt
Type: text/plain
Part: 0
Message: Re: [PoC] Federated Authn/z with OAUTHBEARER
1:  e80c124c3d ! 1:  1e17a1059f common/jsonapi: support FRONTEND clients
    @@ Commit message
         memory owned by the JsonLexContext, so clients don't need to worry about
         freeing it.
     
    -    For convenience, the backend now has destroyJsonLexContext() to mirror
    -    other create/destroy APIs. The frontend has init/term versions of the
    -    API to handle stack-allocated JsonLexContexts.
    -
         We can now partially revert b44669b2ca, now that json_errdetail() works
         correctly.
     
    - ## src/backend/utils/adt/jsonfuncs.c ##
    -@@ src/backend/utils/adt/jsonfuncs.c: json_object_keys(PG_FUNCTION_ARGS)
    - 		pg_parse_json_or_ereport(lex, sem);
    - 		/* keys are now in state->result */
    - 
    --		pfree(lex->strval->data);
    --		pfree(lex->strval);
    --		pfree(lex);
    -+		destroyJsonLexContext(lex);
    - 		pfree(sem);
    - 
    - 		MemoryContextSwitchTo(oldcontext);
    -
      ## src/bin/pg_verifybackup/parse_manifest.c ##
    -@@ src/bin/pg_verifybackup/parse_manifest.c: void
    - json_parse_manifest(JsonManifestParseContext *context, char *buffer,
    - 					size_t size)
    - {
    --	JsonLexContext *lex;
    -+	JsonLexContext lex = {0};
    - 	JsonParseErrorType json_error;
    - 	JsonSemAction sem;
    - 	JsonManifestParseState parse;
    -@@ src/bin/pg_verifybackup/parse_manifest.c: json_parse_manifest(JsonManifestParseContext *context, char *buffer,
    - 	parse.state = JM_EXPECT_TOPLEVEL_START;
    - 	parse.saw_version_field = false;
    - 
    --	/* Create a JSON lexing context. */
    --	lex = makeJsonLexContextCstringLen(buffer, size, PG_UTF8, true);
    -+	/* Initialize a JSON lexing context. */
    -+	initJsonLexContextCstringLen(&lex, buffer, size, PG_UTF8, true);
    - 
    - 	/* Set up semantic actions. */
    - 	sem.semstate = &parse;
     @@ src/bin/pg_verifybackup/parse_manifest.c: json_parse_manifest(JsonManifestParseContext *context, char *buffer,
    - 	sem.scalar = json_manifest_scalar;
    - 
      	/* Run the actual JSON parser. */
    --	json_error = pg_parse_json(lex, &sem);
    -+	json_error = pg_parse_json(&lex, &sem);
    + 	json_error = pg_parse_json(lex, &sem);
      	if (json_error != JSON_SUCCESS)
     -		json_manifest_parse_failure(context, "parsing failed");
    -+		json_manifest_parse_failure(context, json_errdetail(json_error, &lex));
    ++		json_manifest_parse_failure(context, json_errdetail(json_error, lex));
      	if (parse.state != JM_EXPECT_EOF)
      		json_manifest_parse_failure(context, "manifest ended unexpectedly");
      
    - 	/* Verify the manifest checksum. */
    - 	verify_manifest_checksum(&parse, buffer, size);
    -+
    -+	/* Clean up. */
    -+	termJsonLexContext(&lex);
    - }
    - 
    - /*
     
      ## src/bin/pg_verifybackup/t/005_bad_manifest.pl ##
     @@ src/bin/pg_verifybackup/t/005_bad_manifest.pl: use Test::More;
    @@ src/common/jsonapi.c
      /*
       * The context of the parser is maintained by the recursive descent
       * mechanism, but is passed explicitly to the error reporting routine
    -@@ src/common/jsonapi.c: IsValidJsonNumber(const char *str, int len)
    - 	return (!numeric_error) && (total_len == dummy_lex.input_length);
    - }
    - 
    -+#ifndef FRONTEND
    -+
    - /*
    -  * makeJsonLexContextCstringLen
    -  *
    -- * lex constructor, with or without StringInfo object for de-escaped lexemes.
    -+ * lex constructor, with or without a string object for de-escaped lexemes.
    -  *
    -  * Without is better as it makes the processing faster, so only make one
    -  * if really required.
    -@@ src/common/jsonapi.c: makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escape
    - {
    - 	JsonLexContext *lex = palloc0(sizeof(JsonLexContext));
    - 
    -+	initJsonLexContextCstringLen(lex, json, len, encoding, need_escapes);
    -+
    -+	return lex;
    -+}
    -+
    -+void
    -+destroyJsonLexContext(JsonLexContext *lex)
    -+{
    -+	termJsonLexContext(lex);
    -+	pfree(lex);
    -+}
    -+
    -+#endif /* !FRONTEND */
    -+
    -+void
    -+initJsonLexContextCstringLen(JsonLexContext *lex, char *json, int len, int encoding, bool need_escapes)
    -+{
    - 	lex->input = lex->token_terminator = lex->line_start = json;
    - 	lex->line_number = 1;
    - 	lex->input_length = len;
    +@@ src/common/jsonapi.c: makeJsonLexContextCstringLen(JsonLexContext *lex, char *json,
      	lex->input_encoding = encoding;
    --	if (need_escapes)
    + 	if (need_escapes)
    + 	{
     -		lex->strval = makeStringInfo();
    --	return lex;
    -+	lex->parse_strval = need_escapes;
    -+	if (lex->parse_strval)
    -+	{
     +		/*
     +		 * This call can fail in FRONTEND code. We defer error handling to time
    -+		 * of use (json_lex_string()) since there's no way to signal failure
    -+		 * here, and we might not need to parse any strings anyway.
    ++		 * of use (json_lex_string()) since we might not need to parse any
    ++		 * strings anyway.
     +		 */
     +		lex->strval = createStrVal();
    -+	}
    + 		lex->flags |= JSONLEX_FREE_STRVAL;
    ++		lex->parse_strval = true;
    + 	}
     +	lex->errormsg = NULL;
    -+}
    -+
    -+void
    -+termJsonLexContext(JsonLexContext *lex)
    -+{
    + 
    + 	return lex;
    + }
    +@@ src/common/jsonapi.c: makeJsonLexContextCstringLen(JsonLexContext *lex, char *json,
    + void
    + freeJsonLexContext(JsonLexContext *lex)
    + {
     +	static const JsonLexContext empty = {0};
     +
    -+	if (lex->strval)
    -+	{
    + 	if (lex->flags & JSONLEX_FREE_STRVAL)
    + 	{
     +#ifdef FRONTEND
     +		destroyPQExpBuffer(lex->strval);
     +#else
    -+		pfree(lex->strval->data);
    -+		pfree(lex->strval);
    + 		pfree(lex->strval->data);
    + 		pfree(lex->strval);
     +#endif
     +	}
    -+
     +	if (lex->errormsg)
     +	{
     +#ifdef FRONTEND
    @@ src/common/jsonapi.c: makeJsonLexContextCstringLen(char *json, int len, int enco
     +		pfree(lex->errormsg->data);
     +		pfree(lex->errormsg);
     +#endif
    -+	}
    -+
    -+	*lex = empty;
    + 	}
    + 	if (lex->flags & JSONLEX_FREE_STRUCT)
    + 		pfree(lex);
    ++	else
    ++		*lex = empty;
      }
      
      /*
    @@ src/common/jsonapi.c: json_errdetail(JsonParseErrorType error, JsonLexContext *l
     +	return lex->errormsg->data;
     +}
     
    + ## src/common/meson.build ##
    +@@ src/common/meson.build: common_sources_frontend_static += files(
    + # least cryptohash_openssl.c, hmac_openssl.c depend on it.
    + # controldata_utils.c depends on wait_event_types_h. That's arguably a
    + # layering violation, but ...
    ++#
    ++# XXX Frontend builds need libpq's pqexpbuffer.h, so adjust the include paths
    ++# appropriately. This seems completely broken.
    + pgcommon = {}
    + pgcommon_variants = {
    +   '_srv': internal_lib_args + {
    ++    'include_directories': include_directories('.'),
    +     'sources': common_sources + [lwlocknames_h] + [wait_event_types_h],
    +     'dependencies': [backend_common_code],
    +   },
    +   '': default_lib_args + {
    ++    'include_directories': include_directories('../interfaces/libpq', '.'),
    +     'sources': common_sources_frontend_static,
    +     'dependencies': [frontend_common_code],
    +     # Files in libpgcommon.a should use/export the "xxx_private" versions
    +@@ src/common/meson.build: pgcommon_variants = {
    +   },
    +   '_shlib': default_lib_args + {
    +     'pic': true,
    ++    'include_directories': include_directories('../interfaces/libpq', '.'),
    +     'sources': common_sources_frontend_shlib,
    +     'dependencies': [frontend_common_code],
    +   },
    +@@ src/common/meson.build: foreach name, opts : pgcommon_variants
    +     c_args = opts.get('c_args', []) + common_cflags[cflagname]
    +     cflag_libs += static_library('libpgcommon@0@_@1@'.format(name, cflagname),
    +       c_pch: pch_c_h,
    +-      include_directories: include_directories('.'),
    +       kwargs: opts + {
    +         'sources': sources,
    +         'c_args': c_args,
    +@@ src/common/meson.build: foreach name, opts : pgcommon_variants
    +   lib = static_library('libpgcommon@0@'.format(name),
    +       link_with: cflag_libs,
    +       c_pch: pch_c_h,
    +-      include_directories: include_directories('.'),
    +       kwargs: opts + {
    +         'dependencies': opts['dependencies'] + [ssl],
    +       }
    +
      ## src/include/common/jsonapi.h ##
     @@
      #ifndef JSONAPI_H
    @@ src/include/common/jsonapi.h: typedef enum JsonParseErrorType
      	JSON_UNICODE_ESCAPE_FORMAT,
      	JSON_UNICODE_HIGH_ESCAPE,
     @@ src/include/common/jsonapi.h: typedef enum JsonParseErrorType
    - 	JSON_SEM_ACTION_FAILED		/* error should already be reported */
    + 	JSON_SEM_ACTION_FAILED,		/* error should already be reported */
      } JsonParseErrorType;
      
     +/*
    @@ src/include/common/jsonapi.h: typedef enum JsonParseErrorType
      /*
       * All the fields in this structure should be treated as read-only.
     @@ src/include/common/jsonapi.h: typedef struct JsonLexContext
    - 	int			lex_level;
    + 	bits32		flags;
      	int			line_number;	/* line number, starting from 1 */
      	char	   *line_start;		/* where that line starts within input */
     -	StringInfo	strval;
    @@ src/include/common/jsonapi.h: typedef struct JsonLexContext
      } JsonLexContext;
      
      typedef JsonParseErrorType (*json_struct_action) (void *state);
    -@@ src/include/common/jsonapi.h: extern PGDLLIMPORT JsonSemAction nullSemAction;
    -  */
    - extern JsonParseErrorType json_count_array_elements(JsonLexContext *lex,
    - 													int *elements);
    -+#ifndef FRONTEND
    - 
    - /*
    -- * constructor for JsonLexContext, with or without strval element.
    -+ * allocating constructor for JsonLexContext, with or without strval element.
    -  * If supplied, the strval element will contain a de-escaped version of
    -  * the lexeme. However, doing this imposes a performance penalty, so
    -  * it should be avoided if the de-escaped lexeme is not required.
    -@@ src/include/common/jsonapi.h: extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
    - 													int encoding,
    - 													bool need_escapes);
    - 
    -+/*
    -+ * Counterpart to makeJsonLexContextCstringLen(): clears and deallocates lex.
    -+ * The context pointer should not be used after this call.
    -+ */
    -+extern void destroyJsonLexContext(JsonLexContext *lex);
    -+
    -+#endif /* !FRONTEND */
    -+
    -+/*
    -+ * stack constructor for JsonLexContext, with or without strval element.
    -+ * If supplied, the strval element will contain a de-escaped version of
    -+ * the lexeme. However, doing this imposes a performance penalty, so
    -+ * it should be avoided if the de-escaped lexeme is not required.
    -+ */
    -+extern void initJsonLexContextCstringLen(JsonLexContext *lex,
    -+										 char *json,
    -+										 int len,
    -+										 int encoding,
    -+										 bool need_escapes);
    -+
    -+/*
    -+ * Counterpart to initJsonLexContextCstringLen(): clears the contents of lex,
    -+ * but does not deallocate lex itself.
    -+ */
    -+extern void termJsonLexContext(JsonLexContext *lex);
    -+
    - /* lex one token */
    - extern JsonParseErrorType json_lex(JsonLexContext *lex);
    - 
2:  02eea9ffe0 ! 2:  e941ba5807 libpq: add OAUTHBEARER SASL mechanism
    @@ src/Makefile.global.in: with_ldap	= @with_ldap@
      with_uuid	= @with_uuid@
      with_zlib	= @with_zlib@
     
    - ## src/common/meson.build ##
    -@@ src/common/meson.build: common_sources_frontend_static += files(
    - # least cryptohash_openssl.c, hmac_openssl.c depend on it.
    - # controldata_utils.c depends on wait_event_types_h. That's arguably a
    - # layering violation, but ...
    -+#
    -+# XXX Frontend builds need libpq's pqexpbuffer.h, so adjust the include paths
    -+# appropriately. This seems completely broken.
    - pgcommon = {}
    - pgcommon_variants = {
    -   '_srv': internal_lib_args + {
    -+    'include_directories': include_directories('.'),
    -     'sources': common_sources + [lwlocknames_h] + [wait_event_types_h],
    -     'dependencies': [backend_common_code],
    -   },
    -   '': default_lib_args + {
    -+    'include_directories': include_directories('../interfaces/libpq', '.'),
    -     'sources': common_sources_frontend_static,
    -     'dependencies': [frontend_common_code],
    -   },
    -   '_shlib': default_lib_args + {
    -     'pic': true,
    -+    'include_directories': include_directories('../interfaces/libpq', '.'),
    -     'sources': common_sources_frontend_shlib,
    -     'dependencies': [frontend_common_code],
    -   },
    -@@ src/common/meson.build: foreach name, opts : pgcommon_variants
    -     c_args = opts.get('c_args', []) + common_cflags[cflagname]
    -     cflag_libs += static_library('libpgcommon@0@_@1@'.format(name, cflagname),
    -       c_pch: pch_c_h,
    --      include_directories: include_directories('.'),
    -       kwargs: opts + {
    -         'sources': sources,
    -         'c_args': c_args,
    -@@ src/common/meson.build: foreach name, opts : pgcommon_variants
    -   lib = static_library('libpgcommon@0@'.format(name),
    -       link_with: cflag_libs,
    -       c_pch: pch_c_h,
    --      include_directories: include_directories('.'),
    -       kwargs: opts + {
    -         'dependencies': opts['dependencies'] + [ssl],
    -       }
    -
      ## src/include/common/oauth-common.h (new) ##
     @@
     +/*-------------------------------------------------------------------------
    @@ src/interfaces/libpq/fe-auth-oauth-curl.c (new)
     +		goto cleanup;
     +	}
     +
    -+	initJsonLexContextCstringLen(&lex, resp->data, resp->len, PG_UTF8, true);
    ++	makeJsonLexContextCstringLen(&lex, resp->data, resp->len, PG_UTF8, true);
     +
     +	ctx.errbuf = &actx->errbuf;
     +	ctx.fields = fields;
    @@ src/interfaces/libpq/fe-auth-oauth-curl.c (new)
     +	success = true;
     +
     +cleanup:
    -+	termJsonLexContext(&lex);
    ++	freeJsonLexContext(&lex);
     +	return success;
     +}
     +
    @@ src/interfaces/libpq/fe-auth-oauth.c (new)
     +		return false;
     +	}
     +
    -+	initJsonLexContextCstringLen(&lex, msg, msglen, PG_UTF8, true);
    ++	makeJsonLexContextCstringLen(&lex, msg, msglen, PG_UTF8, true);
     +
     +	initPQExpBuffer(&ctx.errbuf);
     +	sem.semstate = &ctx;
    @@ src/interfaces/libpq/fe-auth-oauth.c (new)
     +
     +	/* Don't need the error buffer or the JSON lexer anymore. */
     +	termPQExpBuffer(&ctx.errbuf);
    -+	termJsonLexContext(&lex);
    ++	freeJsonLexContext(&lex);
     +
     +	if (errmsg)
     +		return false;
3:  b3a731b695 ! 3:  37eaa5ceb6 backend: add OAUTHBEARER SASL mechanism
    @@ src/include/libpq/auth.h: extern PGDLLIMPORT bool pg_gss_accept_delegation;
     
      ## src/include/libpq/hba.h ##
     @@ src/include/libpq/hba.h: typedef enum UserAuth
    - 	uaLDAP,
      	uaCert,
      	uaRADIUS,
    --	uaPeer
    + 	uaPeer,
     -#define USER_AUTH_LAST uaPeer	/* Must be last value of this enum */
    -+	uaPeer,
    -+	uaOAuth
    ++	uaOAuth,
     +#define USER_AUTH_LAST uaOAuth	/* Must be last value of this enum */
      } UserAuth;
      
4:  b2a570114e = 4:  7177943f0c Add pytest suite for OAuth
5:  48cd916bfe = 5:  bea695c317 squash! Add pytest suite for OAuth