Skip to content

Commit

Permalink
Fixed connection states not being set correctly.
Browse files Browse the repository at this point in the history
  • Loading branch information
kristoffer-zliide committed May 6, 2024
1 parent 96b81ac commit f92bd08
Showing 1 changed file with 164 additions and 167 deletions.
331 changes: 164 additions & 167 deletions src/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class Connection extends LiteConnection {
/**
* @private
*/
declare STATE: {
STATE: {
INITIALIZED: State;
CONNECTING: State;
SENT_PRELOGIN: State;
Expand All @@ -86,195 +86,192 @@ class Connection extends LiteConnection {
SENT_CLIENT_REQUEST: State;
SENT_ATTENTION: State;
FINAL: State;
};
}
} = {
...LiteConnection.prototype.STATE,
SENT_LOGIN7_WITH_NTLM: {
name: 'SentLogin7WithNTLMLogin',
enter: function() {
(async () => {
this.transitionTo(this.STATE.FINAL);
while (true) {
let message;
try {
message = await this.messageIo.readMessage();
} catch (err: any) {
return this.socketError(err);
}

function isTransientError(error: AggregateError | ConnectionError): boolean {
if (error instanceof AggregateError) {
error = error.errors[0];
}
return (error instanceof ConnectionError) && !!error.isTransient;
}
const handler = new Login7TokenHandler(this);
const tokenStreamParser = this.createTokenStreamParser(message, handler);

export default Connection;
module.exports = Connection;
await once(tokenStreamParser, 'end');

setCodec(iconv);
if (handler.loginAckReceived) {
if (handler.routingData) {
this.routingData = handler.routingData;
return this.transitionTo(this.STATE.REROUTING);
} else {
return this.transitionTo(this.STATE.LOGGED_IN_SENDING_INITIAL_SQL);
}
} else if (this.ntlmpacket) {
const authentication = this.config.authentication as NtlmAuthentication;

Connection.prototype.STATE = {
...LiteConnection.prototype.STATE,
SENT_LOGIN7_WITH_NTLM: {
name: 'SentLogin7WithNTLMLogin',
enter: function() {
(async () => {
this.emit('connect', new ConnectionError('Login through NTLM is not supported in the lite connection. Please switch to the normal connection.', 'ELOGIN'));
this.transitionTo(this.STATE.FINAL);
while (true) {
let message;
try {
message = await this.messageIo.readMessage();
} catch (err: any) {
return this.socketError(err);
}
const payload = new NTLMResponsePayload({
domain: authentication.options.domain,
userName: authentication.options.userName,
password: authentication.options.password,
ntlmpacket: this.ntlmpacket
});

const handler = new Login7TokenHandler(this);
const tokenStreamParser = this.createTokenStreamParser(message, handler);
this.messageIo.sendMessage(TYPE.NTLMAUTH_PKT, payload.data);
this.debug.payload(function() {
return payload.toString(' ');
});

await once(tokenStreamParser, 'end');

if (handler.loginAckReceived) {
if (handler.routingData) {
this.routingData = handler.routingData;
return this.transitionTo(this.STATE.REROUTING);
} else {
return this.transitionTo(this.STATE.LOGGED_IN_SENDING_INITIAL_SQL);
this.ntlmpacket = undefined;
} else if (this.loginError) {
if (isTransientError(this.loginError)) {
this.debug.log('Initiating retry on transient error');
return this.transitionTo(this.STATE.TRANSIENT_FAILURE_RETRY);
} else {
this.emit('connect', this.loginError);
return this.transitionTo(this.STATE.FINAL);
}
} else {
this.emit('connect', new ConnectionError('Login failed.', 'ELOGIN'));
return this.transitionTo(this.STATE.FINAL);
}
}
} else if (this.ntlmpacket) {
const authentication = this.config.authentication as NtlmAuthentication;

const payload = new NTLMResponsePayload({
domain: authentication.options.domain,
userName: authentication.options.userName,
password: authentication.options.password,
ntlmpacket: this.ntlmpacket
});

this.messageIo.sendMessage(TYPE.NTLMAUTH_PKT, payload.data);
this.debug.payload(function() {
return payload.toString(' ');
})().catch((err) => {
process.nextTick(() => {
throw err;
});

this.ntlmpacket = undefined;
} else if (this.loginError) {
if (isTransientError(this.loginError)) {
this.debug.log('Initiating retry on transient error');
return this.transitionTo(this.STATE.TRANSIENT_FAILURE_RETRY);
} else {
this.emit('connect', this.loginError);
return this.transitionTo(this.STATE.FINAL);
}
} else {
this.emit('connect', new ConnectionError('Login failed.', 'ELOGIN'));
return this.transitionTo(this.STATE.FINAL);
});
},
events: {
socketError: function() {
this.transitionTo(this.STATE.FINAL);
},
connectTimeout: function() {
this.transitionTo(this.STATE.FINAL);
}
}

})().catch((err) => {
process.nextTick(() => {
throw err;
});
});
},
events: {
socketError: function() {
this.transitionTo(this.STATE.FINAL);
},
connectTimeout: function() {
this.transitionTo(this.STATE.FINAL);
}
}
},
SENT_LOGIN7_WITH_FEDAUTH: {
name: 'SentLogin7Withfedauth',
enter: function() {
(async () => {
let message;
try {
message = await this.messageIo.readMessage();
} catch (err: any) {
return this.socketError(err);
}
SENT_LOGIN7_WITH_FEDAUTH: {
name: 'SentLogin7Withfedauth',
enter: function() {
(async () => {
let message;
try {
message = await this.messageIo.readMessage();
} catch (err: any) {
return this.socketError(err);
}

const handler = new Login7TokenHandler(this);
const tokenStreamParser = this.createTokenStreamParser(message, handler);
await once(tokenStreamParser, 'end');
if (handler.loginAckReceived) {
if (handler.routingData) {
this.routingData = handler.routingData;
this.transitionTo(this.STATE.REROUTING);
} else {
this.transitionTo(this.STATE.LOGGED_IN_SENDING_INITIAL_SQL);
}
const handler = new Login7TokenHandler(this);
const tokenStreamParser = this.createTokenStreamParser(message, handler);
await once(tokenStreamParser, 'end');
if (handler.loginAckReceived) {
if (handler.routingData) {
this.routingData = handler.routingData;
this.transitionTo(this.STATE.REROUTING);
} else {
this.transitionTo(this.STATE.LOGGED_IN_SENDING_INITIAL_SQL);
}

return;
}
return;
}

const fedAuthInfoToken = handler.fedAuthInfoToken;
const fedAuthInfoToken = handler.fedAuthInfoToken;

if (fedAuthInfoToken && fedAuthInfoToken.stsurl && fedAuthInfoToken.spn) {
const authentication = this.config.authentication as AzureActiveDirectoryPasswordAuthentication | AzureActiveDirectoryMsiVmAuthentication | AzureActiveDirectoryMsiAppServiceAuthentication | AzureActiveDirectoryServicePrincipalSecret | AzureActiveDirectoryDefaultAuthentication;
const tokenScope = new URL('/.default', fedAuthInfoToken.spn).toString();
if (fedAuthInfoToken && fedAuthInfoToken.stsurl && fedAuthInfoToken.spn) {
const authentication = this.config.authentication as AzureActiveDirectoryPasswordAuthentication | AzureActiveDirectoryMsiVmAuthentication | AzureActiveDirectoryMsiAppServiceAuthentication | AzureActiveDirectoryServicePrincipalSecret | AzureActiveDirectoryDefaultAuthentication;
const tokenScope = new URL('/.default', fedAuthInfoToken.spn).toString();

let credentials;
let credentials;

switch (authentication.type) {
case 'azure-active-directory-password':
credentials = new UsernamePasswordCredential(
authentication.options.tenantId ?? 'common',
authentication.options.clientId,
authentication.options.userName,
authentication.options.password
);
break;
case 'azure-active-directory-msi-vm':
case 'azure-active-directory-msi-app-service':
const msiArgs = authentication.options.clientId ? [authentication.options.clientId, {}] : [{}];
credentials = new ManagedIdentityCredential(...msiArgs);
break;
case 'azure-active-directory-default':
const args = authentication.options.clientId ? { managedIdentityClientId: authentication.options.clientId } : {};
credentials = new DefaultAzureCredential(args);
break;
case 'azure-active-directory-service-principal-secret':
credentials = new ClientSecretCredential(
authentication.options.tenantId,
authentication.options.clientId,
authentication.options.clientSecret
);
break;
}
switch (authentication.type) {
case 'azure-active-directory-password':
credentials = new UsernamePasswordCredential(
authentication.options.tenantId ?? 'common',
authentication.options.clientId,
authentication.options.userName,
authentication.options.password
);
break;
case 'azure-active-directory-msi-vm':
case 'azure-active-directory-msi-app-service':
const msiArgs = authentication.options.clientId ? [authentication.options.clientId, {}] : [{}];
credentials = new ManagedIdentityCredential(...msiArgs);
break;
case 'azure-active-directory-default':
const args = authentication.options.clientId ? { managedIdentityClientId: authentication.options.clientId } : {};
credentials = new DefaultAzureCredential(args);
break;
case 'azure-active-directory-service-principal-secret':
credentials = new ClientSecretCredential(
authentication.options.tenantId,
authentication.options.clientId,
authentication.options.clientSecret
);
break;
}

let tokenResponse;
try {
tokenResponse = await credentials.getToken(tokenScope);
} catch (err) {
this.loginError = new AggregateError(
[new ConnectionError('Security token could not be authenticated or authorized.', 'EFEDAUTH'), err]);
this.emit('connect', this.loginError);
this.transitionTo(this.STATE.FINAL);
return;
}
let tokenResponse;
try {
tokenResponse = await credentials.getToken(tokenScope);
} catch (err) {
this.loginError = new AggregateError(
[new ConnectionError('Security token could not be authenticated or authorized.', 'EFEDAUTH'), err]);
this.emit('connect', this.loginError);
this.transitionTo(this.STATE.FINAL);
return;
}


const token = tokenResponse.token;
this.sendFedAuthTokenMessage(token);
const token = tokenResponse.token;
this.sendFedAuthTokenMessage(token);

} else if (this.loginError) {
if (isTransientError(this.loginError)) {
this.debug.log('Initiating retry on transient error');
this.transitionTo(this.STATE.TRANSIENT_FAILURE_RETRY);
} else {
this.emit('connect', this.loginError);
} else if (this.loginError) {
if (isTransientError(this.loginError)) {
this.debug.log('Initiating retry on transient error');
this.transitionTo(this.STATE.TRANSIENT_FAILURE_RETRY);
} else {
this.emit('connect', this.loginError);
this.transitionTo(this.STATE.FINAL);
}
} else {
this.emit('connect', new ConnectionError('Login failed.', 'ELOGIN'));
this.transitionTo(this.STATE.FINAL);
}

})().catch((err) => {
process.nextTick(() => {
throw err;
});
});
},
events: {
socketError: function() {
this.transitionTo(this.STATE.FINAL);
},
connectTimeout: function() {
this.transitionTo(this.STATE.FINAL);
}
} else {
this.emit('connect', new ConnectionError('Login failed.', 'ELOGIN'));
this.transitionTo(this.STATE.FINAL);
}

})().catch((err) => {
process.nextTick(() => {
throw err;
});
});
},
events: {
socketError: function() {
this.transitionTo(this.STATE.FINAL);
},
connectTimeout: function() {
this.transitionTo(this.STATE.FINAL);
}
}
},
};
};
}

function isTransientError(error: AggregateError | ConnectionError): boolean {
if (error instanceof AggregateError) {
error = error.errors[0];
}
return (error instanceof ConnectionError) && !!error.isTransient;
}

export default Connection;
module.exports = Connection;

setCodec(iconv);

0 comments on commit f92bd08

Please sign in to comment.