feat(smartradius): Implement full RADIUS server and client with RFC 2865/2866 compliance, including packet handling, authenticators, attributes, secrets manager, client APIs, and comprehensive tests and documentation
This commit is contained in:
116
ts_server/classes.radiussecrets.ts
Normal file
116
ts_server/classes.radiussecrets.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import type { TSecretResolver } from './interfaces.js';
|
||||
|
||||
/**
|
||||
* RADIUS Shared Secrets Manager
|
||||
* Manages per-client shared secrets for RADIUS authentication
|
||||
*/
|
||||
export class RadiusSecrets {
|
||||
private readonly secrets: Map<string, string> = new Map();
|
||||
private defaultSecret?: string;
|
||||
private customResolver?: TSecretResolver;
|
||||
|
||||
/**
|
||||
* Create a new secrets manager
|
||||
*/
|
||||
constructor(options?: {
|
||||
defaultSecret?: string;
|
||||
secrets?: Record<string, string>;
|
||||
resolver?: TSecretResolver;
|
||||
}) {
|
||||
if (options?.defaultSecret) {
|
||||
this.defaultSecret = options.defaultSecret;
|
||||
}
|
||||
if (options?.secrets) {
|
||||
for (const [ip, secret] of Object.entries(options.secrets)) {
|
||||
this.secrets.set(ip, secret);
|
||||
}
|
||||
}
|
||||
if (options?.resolver) {
|
||||
this.customResolver = options.resolver;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set secret for a specific client IP
|
||||
*/
|
||||
public setClientSecret(clientIp: string, secret: string): void {
|
||||
this.secrets.set(clientIp, secret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove secret for a specific client IP
|
||||
*/
|
||||
public removeClientSecret(clientIp: string): boolean {
|
||||
return this.secrets.delete(clientIp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default secret
|
||||
*/
|
||||
public setDefaultSecret(secret: string): void {
|
||||
this.defaultSecret = secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom resolver
|
||||
*/
|
||||
public setResolver(resolver: TSecretResolver): void {
|
||||
this.customResolver = resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get secret for a client IP
|
||||
* Priority: 1. Custom resolver, 2. Per-client secret, 3. Default secret
|
||||
*/
|
||||
public getSecret(clientIp: string): string | undefined {
|
||||
// Try custom resolver first
|
||||
if (this.customResolver) {
|
||||
const resolved = this.customResolver(clientIp);
|
||||
if (resolved !== undefined) {
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
// Try per-client secret
|
||||
const clientSecret = this.secrets.get(clientIp);
|
||||
if (clientSecret !== undefined) {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
// Fall back to default secret
|
||||
return this.defaultSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a client is known (has a secret)
|
||||
*/
|
||||
public isKnownClient(clientIp: string): boolean {
|
||||
return this.getSecret(clientIp) !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all registered client IPs
|
||||
*/
|
||||
public getClientIps(): string[] {
|
||||
return Array.from(this.secrets.keys());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all per-client secrets
|
||||
*/
|
||||
public clearClientSecrets(): void {
|
||||
this.secrets.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set secrets from a CIDR range (simplified - just IP addresses)
|
||||
* For actual CIDR support, use a custom resolver
|
||||
*/
|
||||
public setSecretsForNetwork(network: string, secret: string): void {
|
||||
// For simplicity, this just sets a single IP
|
||||
// Real CIDR support would require a resolver
|
||||
this.secrets.set(network, secret);
|
||||
}
|
||||
}
|
||||
|
||||
export default RadiusSecrets;
|
||||
Reference in New Issue
Block a user