dovecot-auth-client
Version:
Dovecot authentication socket protocol client for Node
1 lines • 4.86 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import net from 'node:net';\n\ntype DovecotAuthOptions = {\n socketPath?: string;\n service?: string;\n timeout?: number;\n}\n\ntype DovecotResponse = {\n status: string;\n args: string[];\n}\n\ntype AuthState = 'initial' | 'sent-cpid' | 'auth-requested' | 'done';\n\n/**\n * tokenize a Dovecot auth response line.\n */\nconst tokenize = (line: string): string[] => line.trim().split('\\t');\n\n/**\n * fsm automata transition logic for parsing Dovecot socket replies.\n */\nexport function transition(\n state: AuthState,\n line: string,\n socket: net.Socket,\n username: string,\n password: string,\n service: string,\n killTimeout: NodeJS.Timeout,\n resolve: (val: boolean) => void\n): AuthState {\n const tokens = tokenize(line);\n const [command] = tokens;\n\n switch (state) {\n case 'initial':\n if (command === 'OK') {\n socket.write(`CPID\\t${process.pid}\\n`);\n return 'sent-cpid';\n }\n break;\n case 'sent-cpid': {\n const resp = Buffer.from(`${username}\\0${username}\\0${password}`).toString('base64');\n socket.write(`AUTH\\t1\\tPLAIN\\tservice=${service}\\tresp=${resp}\\n`);\n return 'auth-requested';\n }\n case 'auth-requested':\n if (command === 'OK') {\n clearTimeout(killTimeout);\n socket.end();\n resolve(true);\n return 'done';\n } else if (command === 'FAIL' || command === 'NOTFOUND') {\n clearTimeout(killTimeout);\n socket.end();\n resolve(false);\n return 'done';\n }\n break;\n }\n return state;\n}\n\n/**\n * authenticate a user against Dovecot's auth-client socket.\n *\n * @param username - the username to authenticate.\n * @param password - the password to authenticate.\n * @param options - optional configuration.\n * @returns resolves true if auth succeeded, false if not.\n */\nexport async function dovecotAuth(\n username: string,\n password: string,\n options: DovecotAuthOptions = {}\n): Promise<boolean> {\n const {\n socketPath = '/var/run/dovecot/auth-client',\n service = 'smtp',\n timeout = 3000\n } = options;\n\n return new Promise((resolve, reject) => {\n const socket = net.createConnection({ path: socketPath });\n let state: AuthState = 'initial';\n let timedOut = false;\n\n const killTimeout = setTimeout(() => {\n timedOut = true;\n socket.destroy();\n reject(new Error('Dovecot auth timed out'));\n }, timeout);\n\n socket.on('connect', () => {\n socket.write(`VERSION\\t1\\t0\\n`);\n });\n\n socket.on('data', (chunk: Buffer) => {\n const lines = chunk.toString().split('\\n').filter(Boolean);\n for (const line of lines) {\n state = transition(state, line, socket, username, password, service, killTimeout, resolve);\n if (state === 'done') break;\n }\n });\n\n socket.on('error', (err: Error) => {\n if (!timedOut) {\n clearTimeout(killTimeout);\n reject(err);\n }\n });\n\n socket.on('end', () => {\n clearTimeout(killTimeout);\n });\n });\n}\n\nconst defaultExport = { dovecotAuth };\nexport default defaultExport;\n"],"names":["transition","state","line","socket","username","password","service","killTimeout","resolve","tokens","trim","split","tokenize","command","write","process","pid","resp","Buffer","from","toString","clearTimeout","end","async","dovecotAuth","options","socketPath","timeout","Promise","reject","net","createConnection","path","timedOut","setTimeout","destroy","Error","on","chunk","lines","filter","Boolean","err","defaultExport"],"mappings":"uGAuBgBA,EACdC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,GAEA,MAAMC,EAfS,CAACP,GAA2BA,EAAKQ,OAAOC,MAAM,MAe9CC,CAASV,IACjBW,GAAWJ,EAElB,OAAQR,GACN,IAAK,UACH,GAAgB,OAAZY,EAEF,OADAV,EAAOW,MAAM,SAASC,QAAQC,SACvB,YAET,MACF,IAAK,YAAa,CAChB,MAAMC,EAAOC,OAAOC,KAAK,GAAGf,MAAaA,MAAaC,KAAYe,SAAS,UAE3E,OADAjB,EAAOW,MAAM,2BAA2BR,WAAiBW,OAClD,iBAET,IAAK,iBACH,GAAgB,OAAZJ,EAIF,OAHAQ,aAAad,GACbJ,EAAOmB,MACPd,GAAQ,GACD,OACF,GAAgB,SAAZK,GAAkC,aAAZA,EAI/B,OAHAQ,aAAad,GACbJ,EAAOmB,MACPd,GAAQ,GACD,OAIb,OAAOP,CACT,CAUOsB,eAAeC,EACpBpB,EACAC,EACAoB,EAA8B,CAAA,GAE9B,MAAMC,WACJA,EAAa,+BAA8BpB,QAC3CA,EAAU,OAAMqB,QAChBA,EAAU,KACRF,EAEJ,OAAO,IAAIG,SAAQ,CAACpB,EAASqB,KAC3B,MAAM1B,EAAS2B,EAAIC,iBAAiB,CAAEC,KAAMN,IAC5C,IAAIzB,EAAmB,UACnBgC,GAAW,EAEf,MAAM1B,EAAc2B,YAAW,KAC7BD,GAAW,EACX9B,EAAOgC,UACPN,EAAO,IAAIO,MAAM,6BAChBT,GAEHxB,EAAOkC,GAAG,WAAW,KACnBlC,EAAOW,MAAM,sBAGfX,EAAOkC,GAAG,QAASC,IACjB,MAAMC,EAAQD,EAAMlB,WAAWT,MAAM,MAAM6B,OAAOC,SAClD,IAAK,MAAMvC,KAAQqC,EAEjB,GADAtC,EAAQD,EAAWC,EAAOC,EAAMC,EAAQC,EAAUC,EAAUC,EAASC,EAAaC,GACpE,SAAVP,EAAkB,SAI1BE,EAAOkC,GAAG,SAAUK,IACbT,IACHZ,aAAad,GACbsB,EAAOa,OAIXvC,EAAOkC,GAAG,OAAO,KACfhB,aAAad,QAGnB,CAEA,MAAMoC,EAAgB,CAAEnB"}