netatalk: uams_srp.c File Reference

netatalk 4.5.1
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
uams_srp.c File Reference
`#include <arpa/inet.h>`
`#include <ctype.h>`
`#include <errno.h>`
`#include <fcntl.h>`
`#include <gcrypt.h>`
`#include <pwd.h>`
`#include <stdarg.h>`
`#include <stdio.h>`
`#include <stdlib.h>`
`#include <sys/param.h>`
`#include <string.h>`
`#include <sys/stat.h>`
`#include <sys/types.h>`
`#include <unistd.h>`
`#include <atalk/afp.h>`
`#include <atalk/constant_time.h>`
`#include <atalk/logger.h>`
`#include <atalk/uam.h>`

## Macros
#define | SRP_INIT_MARKER 0x0001
#define | SRP_CLIENT_PROOF 0x0003
#define | SRP_SERVER_PROOF 0x0004
#define | SRP_SHA1_LEN 20
#define | SRP_SALT_LEN 16
#define | SRP_GROUP_INDEX 0x0002 /* RFC 5054 group #2 */
#define | SRP_NBYTES 192 /* 1536-bit prime = 192 bytes */
#define | SRP_SESSION_KEY_LEN 40
#define | SRP_HEX_SALT_LEN (SRP_SALT_LEN * 2)
#define | SRP_HEX_V_LEN (SRP_NBYTES * 2)
#define | SRP_AUTH_FAILURE (-6754)
#define | unhex(x)

## Functions
static const unsigned char * | strip_leading_zeros (const unsigned char *buf, size_t len, size_t *out_len)
| Strip leading zero bytes from a big-endian integer buffer.
static int | mgf1_sha1 (const unsigned char *seed, size_t seed_len, unsigned char *out, size_t out_len)
| MGF1 mask generation function (PKCS#1 v2.1) with SHA-1.
static int | sha1_multi (unsigned char *out,...)
| Compute SHA-1 incrementally from multiple buffers.
static void | mpi_to_padded_buf (unsigned char *buf, size_t nbytes, gcry_mpi_t m)
| Write an MPI to a buffer as a big-endian integer, zero-padded.
static void | write_uint16_be (unsigned char **p, uint16_t val)
| Write a 2-byte big-endian unsigned integer and advance the pointer.
static uint16_t | read_uint16_be (unsigned char **p)
| Read a 2-byte big-endian unsigned integer and advance the pointer.
static int | srp_lookup_verifier (const char *path, const char *username, unsigned char *salt_out, gcry_mpi_t *v_out)
| Look up a user's salt and verifier from the SRP verifier file.
static void | srp_session_free (void)
| Release all per-session SRP state and zero sensitive buffers.
static int | srp_setup (void *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
| SRP Round 1 setup.
static int | srp_login (void *obj, struct passwd **uam_pwd, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
| FPLogin handler for SRP UAM.
static int | srp_login_ext (void *obj, char *uname, struct passwd **uam_pwd, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
| FPLoginExt handler for SRP UAM.
static int | srp_logincont (void *obj, struct passwd **uam_pwd, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
| SRP Round 2: FPLoginCont handler.
static int | uam_setup (void *obj, const char *path)
static void | uam_cleanup (void)

## Variables
static const unsigned char | srp_N_bytes [SRP_NBYTES]
static const unsigned char | srp_g_byte = 0x02
static gcry_mpi_t | session_N
static gcry_mpi_t | session_g
static gcry_mpi_t | session_v
static gcry_mpi_t | session_b
static gcry_mpi_t | session_B
static unsigned char | session_salt [SRP_SALT_LEN]
static unsigned char | session_B_buf [SRP_NBYTES]
static char | session_username [UAM_USERNAMELEN+1]
static struct passwd * | srppwd
UAM_MODULE_EXPORT struct uam_export | uams_srp

## Detailed Description

SRP (Secure Remote Password) User Authentication Method for AFP. Protocol: SRP-6a with SHA-1, MGF1 KDF, RFC 5054 group #2 (1536-bit).

## Macro Definition Documentation

## ◆ SRP_AUTH_FAILURE

#define SRP_AUTH_FAILURE (-6754)

## ◆ SRP_CLIENT_PROOF

#define SRP_CLIENT_PROOF 0x0003

## ◆ SRP_GROUP_INDEX

#define SRP_GROUP_INDEX 0x0002 /* RFC 5054 group #2 */

## ◆ SRP_HEX_SALT_LEN

#define SRP_HEX_SALT_LEN (SRP_SALT_LEN * 2)

## ◆ SRP_HEX_V_LEN

#define SRP_HEX_V_LEN (SRP_NBYTES * 2)

## ◆ SRP_INIT_MARKER

#define SRP_INIT_MARKER 0x0001

## ◆ SRP_NBYTES

#define SRP_NBYTES 192 /* 1536-bit prime = 192 bytes */

## ◆ SRP_SALT_LEN

#define SRP_SALT_LEN 16

## ◆ SRP_SERVER_PROOF

#define SRP_SERVER_PROOF 0x0004

## ◆ SRP_SESSION_KEY_LEN

#define SRP_SESSION_KEY_LEN 40

## ◆ SRP_SHA1_LEN

#define SRP_SHA1_LEN 20

## ◆ unhex

#define unhex | ( |  | x | ) |

Value:
(isdigit(x) ? (x) - '0' : toupper(x) + 10 - 'A')

## Function Documentation

## ◆ mgf1_sha1()

int mgf1_sha1 | ( | const unsigned char * | seed,
|  | size_t | seed_len,
|  | unsigned char * | out,
|  | size_t | out_len )
| static

MGF1 mask generation function (PKCS#1 v2.1) with SHA-1.

Parameters

  [in] | seed | The seed for the mask generation.
  [in] | seed_len | The length of the seed.
  [out] | out | The output buffer.
  [in] | out_len | The length of the output buffer.

Returns
  0 on success, -1 on failure.

## ◆ mpi_to_padded_buf()

void mpi_to_padded_buf | ( | unsigned char * | buf,
|  | size_t | nbytes,
|  | gcry_mpi_t | m )
| static

Write an MPI to a buffer as a big-endian integer, zero-padded.

Parameters

  [out] | buf | Output buffer (must be at least `nbytes`).
  [in] | nbytes | Target length with leading zero padding.
  [in] | m | MPI to serialize.

## ◆ read_uint16_be()

uint16_t read_uint16_be | ( | unsigned char ** | p | ) |
| static

Read a 2-byte big-endian unsigned integer and advance the pointer.

Parameters

  [in,out] | p | Pointer to the read position (advanced by 2).

Returns
  The decoded 16-bit value.

## ◆ sha1_multi()

int sha1_multi | ( | unsigned char * | out,
|  |  | ... )
| static

Compute SHA-1 incrementally from multiple buffers.

Arguments after `out` are pairs of (const unsigned char *data, size_t len), terminated by a NULL data pointer.

Parameters

  [out] | out | 20-byte buffer for the SHA-1 digest.

Returns
  0 on success, -1 on failure.

## ◆ srp_login()

int srp_login | ( | void * | obj,
|  | struct passwd ** | uam_pwd,
|  | char * | ibuf,
|  | size_t | ibuflen,
|  | char * | rbuf,
|  | size_t * | rbuflen )
| static

FPLogin handler for SRP UAM.

Parses the username from the non-extended login request, validates the user, and delegates to srp_setup() for Round 1.

## ◆ srp_login_ext()

int srp_login_ext | ( | void * | obj,
|  | char * | uname,
|  | struct passwd ** | uam_pwd,
|  | char * | ibuf,
|  | size_t | ibuflen,
|  | char * | rbuf,
|  | size_t * | rbuflen )
| static

FPLoginExt handler for SRP UAM.

Parses the UTF-8 username from the extended login request, validates the user, and delegates to srp_setup() for Round 1.

## ◆ srp_logincont()

int srp_logincont | ( | void * | obj,
|  | struct passwd ** | uam_pwd,
|  | char * | ibuf,
|  | size_t | ibuflen,
|  | char * | rbuf,
|  | size_t * | rbuflen )
| static

SRP Round 2: FPLoginCont handler.

Parses the client's public ephemeral A and proof M1, computes the server-side shared secret S and session key K, verifies M1, and responds with server proof M2 to complete mutual authentication.

Returns
  AFP_OK on success, AFPERR_NOTAUTH on proof mismatch.

## ◆ srp_lookup_verifier()

int srp_lookup_verifier | ( | const char * | path,
|  | const char * | username,
|  | unsigned char * | salt_out,
|  | gcry_mpi_t * | v_out )
| static

Look up a user's salt and verifier from the SRP verifier file.

The file format is one line per user: username:hex_salt:hex_verifier

Parameters

  [in] | path | Path to the verifier file.
  [in] | username | User to look up.
  [out] | salt_out | Buffer for the salt (SRP_SALT_LEN bytes).
  [out] | v_out | MPI set to the verifier on success.

Returns
  0 on success, -1 on failure (user not found or file error).

## ◆ srp_session_free()

void srp_session_free | ( | void |  | ) |
| static

Release all per-session SRP state and zero sensitive buffers.

## ◆ srp_setup()

int srp_setup | ( | void * | obj,
|  | char * | ibuf,
|  | size_t | ibuflen,
|  | char * | rbuf,
|  | size_t * | rbuflen )
| static

SRP Round 1 setup.

Looks up the user's verifier from the verifier file, generates the server ephemeral key pair (b, B), and builds the FPLoginExt response containing the SRP group parameters, salt, and server public ephemeral B.

Returns
  AFPERR_AUTHCONT on success, AFPERR_NOTAUTH if user not found.

## ◆ strip_leading_zeros()

const unsigned char * strip_leading_zeros | ( | const unsigned char * | buf,
|  | size_t | len,
|  | size_t * | out_len )
| static

Strip leading zero bytes from a big-endian integer buffer.

Returns
  pointer to the first non-zero byte (or last byte if all zeros).

## ◆ uam_cleanup()

void uam_cleanup | ( | void |  | ) |
| static

## ◆ uam_setup()

int uam_setup | ( | void * | obj,
|  | const char * | path )
| static

## ◆ write_uint16_be()

void write_uint16_be | ( | unsigned char ** | p,
|  | uint16_t | val )
| static

Write a 2-byte big-endian unsigned integer and advance the pointer.

Parameters

  [in,out] | p | Pointer to the write position (advanced by 2).
  [in] | val | Value to write.

## Variable Documentation

## ◆ session_B

gcry_mpi_t session_B
| static

## ◆ session_b

gcry_mpi_t session_b
| static

## ◆ session_B_buf

unsigned char session_B_buf[SRP_NBYTES]
| static

## ◆ session_g

gcry_mpi_t session_g
| static

## ◆ session_N

gcry_mpi_t session_N
| static

## ◆ session_salt

unsigned char session_salt[SRP_SALT_LEN]
| static

## ◆ session_username

char session_username[UAM_USERNAMELEN+1]
| static

## ◆ session_v

gcry_mpi_t session_v
| static

## ◆ srp_g_byte

const unsigned char srp_g_byte = 0x02
| static

## ◆ srp_N_bytes

const unsigned char srp_N_bytes[SRP_NBYTES]
| static

Initial value:
= {
0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A,
0xB1, 0xF1, 0x2A, 0x86, 0x17, 0xA4, 0x7B, 0xBB,
0xDB, 0xA5, 0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80,
0xBE, 0xEE, 0xA9, 0x61, 0x4B, 0x19, 0xCC, 0x4D,
0x5F, 0x4F, 0x5F, 0x55, 0x6E, 0x27, 0xCB, 0xDE,
0x51, 0xC6, 0xA9, 0x4B, 0xE4, 0x60, 0x7A, 0x29,
0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0, 0xF8, 0x43,
0x80, 0xB6, 0x55, 0xBB, 0x9A, 0x22, 0xE8, 0xDC,
0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0,
0x81, 0x34, 0xB1, 0xC8, 0xB9, 0x79, 0x89, 0x14,
0x9B, 0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D,
0x47, 0x54, 0x83, 0x81, 0xDB, 0xC5, 0xB1, 0xFC,
0x76, 0x4E, 0x3F, 0x4B, 0x53, 0xDD, 0x9D, 0xA1,
0x15, 0x8B, 0xFD, 0x3E, 0x2B, 0x9C, 0x8C, 0xF5,
0x6E, 0xDF, 0x01, 0x95, 0x39, 0x34, 0x96, 0x27,
0xDB, 0x2F, 0xD5, 0x3D, 0x24, 0xB7, 0xC4, 0x86,
0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F, 0x8C,
0xE4, 0x42, 0x73, 0x4A, 0xF7, 0xCC, 0xB7, 0xAE,
0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8,
0x7F, 0x8A, 0x2F, 0xE9, 0xB8, 0xB5, 0x29, 0x2E,
0x5A, 0x02, 0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E,
0x8C, 0xE7, 0xA2, 0x8C, 0x24, 0x42, 0xC6, 0xF3,
0x15, 0x18, 0x0F, 0x93, 0x49, 0x9A, 0x23, 0x4D,
0xCF, 0x76, 0xE3, 0xFE, 0xD1, 0x35, 0xF9, 0xBB,
}

RFC 5054 group #2: 1536-bit MODP group. N is the safe prime, g = 2.

## ◆ srppwd

struct passwd* srppwd
| static

## ◆ uams_srp

UAM_MODULE_EXPORT struct uam_export uams_srp

Initial value:
= {
UAM_MODULE_SERVER,
UAM_MODULE_VERSION,
uam_setup, uam_cleanup
}
UAM_MODULE_VERSION
#define UAM_MODULE_VERSION
Definition uam.h:21
UAM_MODULE_SERVER
#define UAM_MODULE_SERVER
Definition uam.h:17
uam_setup
static int uam_setup(void *obj, const char *path)
Definition uams_dhx2_pam.c:1077
uam_cleanup
static void uam_cleanup(void)
Definition uams_dhx2_pam.c:1099