Skip to content

Commit

Permalink
Merge pull request #621 from MichaelVoelkel/natsOptions_SetUserCreden…
Browse files Browse the repository at this point in the history
…tialsFromMemory

add natsOptions_SetUserCredentialsFromMemory
  • Loading branch information
kozlovic authored Jan 5, 2023
2 parents 2b8543a + e2ba5a0 commit 6d22e57
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 48 deletions.
13 changes: 9 additions & 4 deletions src/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ _connectProto(natsConnection *nc, char **proto)
if (opts->userJWTHandler != NULL)
{
char *errTxt = NULL;
bool userCb = opts->userJWTHandler != natsConn_userFromFile;
bool userCb = opts->userJWTHandler != natsConn_userCreds;

// If callback is not the internal one, we need to release connection lock.
if (userCb)
Expand Down Expand Up @@ -4222,12 +4222,15 @@ _getJwtOrSeed(char **val, const char *fn, bool seed, int item)
}

natsStatus
natsConn_userFromFile(char **userJWT, char **customErrTxt, void *closure)
natsConn_userCreds(char **userJWT, char **customErrTxt, void *closure)
{
natsStatus s = NATS_OK;
userCreds *uc = (userCreds*) closure;

s = _getJwtOrSeed(userJWT, uc->userOrChainedFile, false, 0);
if (uc->jwtAndSeedContent != NULL)
s = nats_GetJWTOrSeed(userJWT, uc->jwtAndSeedContent, 0);
else
s = _getJwtOrSeed(userJWT, uc->userOrChainedFile, false, 0);

return NATS_UPDATE_ERR_STACK(s);
}
Expand All @@ -4238,7 +4241,9 @@ _sign(userCreds *uc, const unsigned char *input, int inputLen, unsigned char *si
natsStatus s = NATS_OK;
char *encodedSeed = NULL;

if (uc->seedFile != NULL)
if (uc->jwtAndSeedContent != NULL)
s = nats_GetJWTOrSeed(&encodedSeed, uc->jwtAndSeedContent, 1);
else if (uc->seedFile != NULL)
s = _getJwtOrSeed(&encodedSeed, uc->seedFile, true, 0);
else
s = _getJwtOrSeed(&encodedSeed, uc->userOrChainedFile, true, 1);
Expand Down
2 changes: 1 addition & 1 deletion src/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ natsStatus
natsConn_publish(natsConnection *nc, natsMsg *msg, const char *reply, bool directFlush);

natsStatus
natsConn_userFromFile(char **userJWT, char **customErrTxt, void *closure);
natsConn_userCreds(char **userJWT, char **customErrTxt, void *closure);

natsStatus
natsConn_signatureHandler(char **customErrTxt, unsigned char **sig, int *sigLen, const char *nonce, void *closure);
Expand Down
17 changes: 17 additions & 0 deletions src/nats.h
Original file line number Diff line number Diff line change
Expand Up @@ -2970,6 +2970,23 @@ natsOptions_SetUserCredentialsFromFiles(natsOptions *opts,
const char *userOrChainedFile,
const char *seedFile);

/** \brief Sets JWT handler and handler to sign nonce that uses seed.
*
* This function acts similarly to natsOptions_SetUserCredentialsFromFiles but reads from memory instead
* from a file. Also it assumes that `memory` contains both the JWT and NKey seed.
*
* As for the format, @cf `natsOptions_SetUserCredentialsFromFiles` documentation.
*
* @see natsOptions_SetUserCredentialsFromFiles()
*
* @param opts the pointer to the #natsOptions object.
* @param memory string containing user JWT and user NKey seed
*
*/
NATS_EXTERN natsStatus
natsOptions_SetUserCredentialsFromMemory(natsOptions *opts,
const char *jwtAndSeedContent);

/** \brief Sets the NKey public key and signature callback.
*
* Any time the library creates a TCP connection to the server, the server
Expand Down
8 changes: 5 additions & 3 deletions src/natsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ typedef struct __userCreds
{
char *userOrChainedFile;
char *seedFile;
char *jwtAndSeedContent;

} userCreds;

Expand Down Expand Up @@ -281,7 +282,7 @@ struct __natsOptions
bool retryOnFailedConnect;

// Callback/closure used to get the user JWT. Will be set to
// internal natsConn_userFromFile function when userCreds != NULL.
// internal natsConn_userCreds function when userCreds != NULL.
natsUserJWTHandler userJWTHandler;
void *userJWTClosure;

Expand All @@ -294,8 +295,9 @@ struct __natsOptions
// to the server.
char *nkey;

// If user has invoked natsOptions_SetUserCredentialsFromFiles, this
// will be set and points to userOrChainedFile and possibly seedFile.
// If user has invoked natsOptions_SetUserCredentialsFromFiles or
// natsOptions_SetUserCredentialsFromMemory, this will be set and points to
// userOrChainedFile, seedFile, or possibly directly contains the JWT+seed content.
struct __userCreds *userCreds;

// Reconnect jitter added to reconnect wait
Expand Down
122 changes: 86 additions & 36 deletions src/opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -1108,11 +1108,12 @@ _freeUserCreds(userCreds *uc)

NATS_FREE(uc->userOrChainedFile);
NATS_FREE(uc->seedFile);
NATS_FREE(uc->jwtAndSeedContent);
NATS_FREE(uc);
}

static natsStatus
_createUserCreds(userCreds **puc, bool onlySeedFile, const char *uocf, const char *sf)
_createUserCreds(userCreds **puc, const char *uocf, const char *sf, const char* jwtAndSeedContent)
{
natsStatus s = NATS_OK;
userCreds *uc = NULL;
Expand All @@ -1121,17 +1122,27 @@ _createUserCreds(userCreds **puc, bool onlySeedFile, const char *uocf, const cha
if (uc == NULL)
return nats_setDefaultError(NATS_NO_MEMORY);

if (!onlySeedFile)
// in case of content, we do not need to read the files anymore
if (jwtAndSeedContent != NULL)
{
uc->userOrChainedFile = NATS_STRDUP(uocf);
if (uc->userOrChainedFile == NULL)
uc->jwtAndSeedContent = NATS_STRDUP(jwtAndSeedContent);
if (uc->jwtAndSeedContent == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
}
if ((s == NATS_OK) && sf != NULL)
else
{
uc->seedFile = NATS_STRDUP(sf);
if (uc->seedFile == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
if (uocf)
{
uc->userOrChainedFile = NATS_STRDUP(uocf);
if (uc->userOrChainedFile == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
}
if ((s == NATS_OK) && sf != NULL)
{
uc->seedFile = NATS_STRDUP(sf);
if (uc->seedFile == NULL)
s = nats_setDefaultError(NATS_NO_MEMORY);
}
}
if (s != NATS_OK)
_freeUserCreds(uc);
Expand All @@ -1141,6 +1152,41 @@ _createUserCreds(userCreds **puc, bool onlySeedFile, const char *uocf, const cha
return NATS_UPDATE_ERR_STACK(s);
}

static void
_setAndUnlockOptsFromUserCreds(natsOptions *opts, userCreds *uc)
{
// Free previous object
_freeUserCreds(opts->userCreds);
// Set to new one (possibly NULL)
opts->userCreds = uc;

if (uc != NULL)
{
opts->userJWTHandler = natsConn_userCreds;
opts->userJWTClosure = (void*) uc;

opts->sigHandler = natsConn_signatureHandler;
opts->sigClosure = (void*) uc;

// NKey and UserCreds are mutually exclusive.
if (opts->nkey != NULL)
{
NATS_FREE(opts->nkey);
opts->nkey = NULL;
}
}
else
{
opts->userJWTHandler = NULL;
opts->userJWTClosure = NULL;

opts->sigHandler = NULL;
opts->sigClosure = NULL;
}

UNLOCK_OPTS(opts);
}

natsStatus
natsOptions_SetUserCredentialsFromFiles(natsOptions *opts, const char *userOrChainedFile, const char *seedFile)
{
Expand All @@ -1159,44 +1205,40 @@ natsOptions_SetUserCredentialsFromFiles(natsOptions *opts, const char *userOrCha

if (!nats_IsStringEmpty(userOrChainedFile))
{
s = _createUserCreds(&uc, false, userOrChainedFile, seedFile);
s = _createUserCreds(&uc, userOrChainedFile, seedFile, NULL);
if (s != NATS_OK)
{
UNLOCK_OPTS(opts);
return NATS_UPDATE_ERR_STACK(s);
}
}

// Free previous object
_freeUserCreds(opts->userCreds);
// Set to new one (possibly NULL)
opts->userCreds = uc;
_setAndUnlockOptsFromUserCreds(opts, uc);

if (uc != NULL)
{
opts->userJWTHandler = natsConn_userFromFile;
opts->userJWTClosure = (void*) uc;
return NATS_OK;
}

opts->sigHandler = natsConn_signatureHandler;
opts->sigClosure = (void*) uc;
natsStatus
natsOptions_SetUserCredentialsFromMemory(natsOptions *opts, const char *jwtAndSeedContent)
{
natsStatus s = NATS_OK;
userCreds *uc = NULL;

// NKey and UserCreds are mutually exclusive.
if (opts->nkey != NULL)
LOCK_AND_CHECK_OPTIONS(opts, 0);

// if content is not NULL create user creds from it;
// otherwise NULL will later lead to setting handlers to NULL
if (jwtAndSeedContent != NULL)
{
s = _createUserCreds(&uc, NULL, NULL, jwtAndSeedContent);
if (s != NATS_OK)
{
NATS_FREE(opts->nkey);
opts->nkey = NULL;
UNLOCK_OPTS(opts);
return NATS_UPDATE_ERR_STACK(s);
}
}
else
{
opts->userJWTHandler = NULL;
opts->userJWTClosure = NULL;

opts->sigHandler = NULL;
opts->sigClosure = NULL;
}

UNLOCK_OPTS(opts);
_setAndUnlockOptsFromUserCreds(opts, uc);

return NATS_OK;
}
Expand Down Expand Up @@ -1302,7 +1344,7 @@ natsOptions_SetNKeyFromSeed(natsOptions *opts,
UNLOCK_OPTS(opts);
return nats_setDefaultError(NATS_NO_MEMORY);
}
s = _createUserCreds(&uc, true, NULL, seedFile);
s = _createUserCreds(&uc, NULL, seedFile, NULL);
if (s != NATS_OK)
{
NATS_FREE(nk);
Expand Down Expand Up @@ -1527,9 +1569,17 @@ natsOptions_clone(natsOptions *opts)
}
else if ((s == NATS_OK) && (opts->userCreds != NULL))
{
s = natsOptions_SetUserCredentialsFromFiles(cloned,
opts->userCreds->userOrChainedFile,
opts->userCreds->seedFile);
if (opts->userCreds->jwtAndSeedContent != NULL)
{
s = natsOptions_SetUserCredentialsFromMemory(cloned,
opts->userCreds->jwtAndSeedContent);
}
else
{
s = natsOptions_SetUserCredentialsFromFiles(cloned,
opts->userCreds->userOrChainedFile,
opts->userCreds->seedFile);
}
}
if ((s == NATS_OK) && (opts->inboxPfx != NULL))
s = _setCustomInboxPrefix(cloned, opts->inboxPfx, false);
Expand Down
1 change: 1 addition & 0 deletions test/list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ GetRTT
GetLocalIPAndPort
UserCredsCallbacks
UserCredsFromFiles
UserCredsFromMemory
NKey
NKeyFromSeed
ConnSign
Expand Down
Loading

0 comments on commit 6d22e57

Please sign in to comment.