All files / src/sso connect.ts

86% Statements 43/50
70% Branches 14/20
100% Functions 1/1
86% Lines 43/50

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 1061x 1x             1x 1x   1x                   1x 1x 1x   1x 1x       1x       1x 1x 1x           1x       1x 1x 2x 2x   2x 1x 1x   2x 2x 2x 2x             2x 2x 1x     2x 2x 2x                   2x 2x 1x     1x 1x     1x 2x 1x 1x       1x 1x            
import { hexDump } from './misc';
import {
  sspi,
  UserCredential,
  SecurityContext,
  InitializeSecurityContextInput,
  AcceptSecurityContextInput,
} from '../../lib/api';
import { SSO } from './SSO';
import dbg from 'debug';
 
const debug = dbg('node-expose-sspi:connect');
 
/**
 * Retrieves SSO information from an explicit credential (login/password and domain).
 * The SSO information will be retrieved only if the credential
 * matches a local account or a domain account.
 *
 * @param {sspi.UserCredential} userCredential
 * @returns {SSO} the SSO object.
 */
export async function connect(userCredential: UserCredential): Promise<SSO> {
  const errorMsg = 'Error while building the security context';
  const badLoginPasswordError = new Error('Sorry mate, wrong login/password.');
  try {
    const packageInfo = sspi.QuerySecurityPackageInfo('Negotiate');
    const clientCred = sspi.AcquireCredentialsHandle({
      packageName: 'Negotiate',
      authData: userCredential,
    });
    const serverCred = sspi.AcquireCredentialsHandle({
      packageName: 'Negotiate',
    });
 
    let serverSecurityContext: SecurityContext;
    let clientSecurityContext: SecurityContext;
    const clientInput: InitializeSecurityContextInput = {
      credential: clientCred.credential,
      targetName: 'kiki',
      cbMaxToken: packageInfo.cbMaxToken,
    };
 
    const serverInput: AcceptSecurityContextInput = {
      credential: serverCred.credential,
      clientSecurityContext: undefined,
    };
    let i = 0;
    while (true) {
      debug('i: ', i);
      i++;
 
      if (serverSecurityContext) {
        clientInput.serverSecurityContext = serverSecurityContext;
        clientInput.contextHandle = clientSecurityContext.contextHandle;
      }
      clientSecurityContext = sspi.InitializeSecurityContext(clientInput);
      debug('clientSecurityContext: ', clientSecurityContext);
      debug(hexDump(clientSecurityContext.SecBufferDesc.buffers[0]));
      Iif (
        clientSecurityContext.SECURITY_STATUS !== 'SEC_I_CONTINUE_NEEDED' &&
        clientSecurityContext.SECURITY_STATUS !== 'SEC_E_OK'
      ) {
        throw errorMsg;
      }
 
      serverInput.clientSecurityContext = clientSecurityContext;
      if (serverSecurityContext) {
        serverInput.contextHandle = serverSecurityContext.contextHandle;
      }
 
      serverSecurityContext = sspi.AcceptSecurityContext(serverInput);
      debug('serverSecurityContext: ', serverSecurityContext);
      Iif (
        serverSecurityContext.SECURITY_STATUS !== 'SEC_I_CONTINUE_NEEDED' &&
        serverSecurityContext.SECURITY_STATUS !== 'SEC_E_OK'
      ) {
        if (serverSecurityContext.SECURITY_STATUS === 'SEC_E_LOGON_DENIED') {
          throw badLoginPasswordError;
        }
        throw errorMsg;
      }
 
      debug(hexDump(serverSecurityContext.SecBufferDesc.buffers[0]));
      if (serverSecurityContext.SECURITY_STATUS !== 'SEC_E_OK') {
        continue;
      }
      // we have the security context !!!
      debug('We have the security context !!!');
      break;
    }
 
    const sso = new SSO(serverSecurityContext.contextHandle);
    await sso.load();
    Eif (sso.user.name === 'Guest') {
      throw badLoginPasswordError;
    }
    return sso;
  } catch (e) {
    Eif (e === badLoginPasswordError) {
      throw e;
    }
    console.error('error', e);
    throw e;
  }
}