Handbok för Sun Enterprise Authentication Mechanism

Kapitel 8 Säker nätverksprogrammering med RPCSEC_GSS

Program som utför åtgärder i nätverket måste använda säkra transaktioner. Med programgränssnittet (API) RPCSEC_GSS kan utvecklare använda en mängd olika säkerhetsmekanismer, bl a SEAM och Kerberos V5. RPCSEC_GSS innehåller även tjänster för integritet (integrity) och skydd av personuppgifter (privacy), vilka ger ytterliggare skydd utöver verifiering. Även om RPCSEC_GSS inte är nödvändigt för, eller utgör en del av, SEAM är det ändå en bra funktion för programmerare som vill utnyttja Kerberos V5 i sina program. Utvecklare som inte använder SEAM/Kerberos V5 som säkerhetsmekanism bör använda RPCSEC_GSS eftersom det är oberoende av mekanismer.

I det här kapitlet förutsätts att du känner till RPC-programmering; mer information om RPC finns i ONC+ Developer's Guide. Kapitlet är endast avsett som en översikt. Om du vill ha information om något särskilt i RPCSEC_GSS, t ex funktioner eller datastrukturer, kan du läsa direkthjälpsavsnittet (man page) rpcsec_gss(3N) eller direkthjälpsavsnitten för funktionerna som beskrivs i kapitlet.

I det här kapitlet behandlas följande:

Säkerhetsalternativ

Det här avsnittet beskriver utvecklingen av och funktionen hos API:t för RPCSEC_GSS.

Säkerhetsfunktioner före RPCSEC_GSS

Ett av de första säkerhetsalternativ som stöddes av RPC var AUTH_SYS (kallas även AUTH_UNIX). AUTH_SYS gav en UNIX-liknande referensfunktion, med identifikationsnummer för grupper och användare, för att identifiera avsändare och mottagare av meddelanden. Det är enkelt att implementera AUTH_SYS, men det är samtidigt enkelt att förbigå funktionen eftersom den inte har äkta verifiering - det finns inget sätt för servern att verifiera att klienten verkligen är den som den utger sig för att vara. Därför är det ganska enkelt att förfalska nätverksanrop under AUTH_SYS.

Ett senare säkerhetsalternativ, AUTH_DES, introducerades strax efter AUTH_SYS. AUTH_DES är baserat på verifiering med offentliga nycklar - funktioner använder nyckelutväxling enligt Diffie-Hellman för att skapa en gemensam nyckel mellan klientens privata nyckel och serverns offentliga nyckel. Den gemensamma nyckeln används sedan för kryptering av en DES-sessionsnyckel, vilken sedan dekrypteras av servern så att en session kan upprättas.

Trots att AUTH_DES är klart bättre än AUTH_SYS finns det ett par begränsningar som har gjort att funktionen aldrig fått någon större utbredning. Det största problemet enligt många användare är att nycklarna är underdimensionerade enligt dagens krypteringsstandarder.

Därför lanserades så småningom ytterligare ett säkerhetsalternativ för RPC. AUTH_KERB, baserat på Kerberos V4, ger bättre säkerhet än både AUTH_DES och AUTH_SYS. AUTH_KERB är dock inte helt säkert.

Mer information om de här säkerhetsalternativen finns i ONC+ Developer's Guide.

Integritet och skydd av personuppgifter: API:t för GSS

Ett nytt nätverksskikt, API:t för GSS (Generic Security Standard), har lagts till för att förbättra säkerheten. Ramverket för API:t för GSS innehåller förutom verifiering två ytterligare säkerhetstjänster:


Obs!

För närvarande visas inte GSS-API:t. Vissa GSS-API-funktioner är dock "synliga" via RPCSEC_GSS-funktioner - de kan ändras "indirekt". Programmeraren behöver inte direkt ta hänsyn till funktionernas värden.


API:t för RPCSEC_GSS

Med säkerhetsalternativet RPCSEC_GSS kan ONC-RPC-program använda funktionerna i GSS-API:t. RPCSEC_GSS är placerat "ovanpå" GSS-API-lagret enligt följande:

Figur 8-1 Säkerhetslagren GSS-API och RPCSEC_GSS

Graphic

Med programmeringsgränssnittet för RPCSEC_GSS kan ONC-RPC-program ange:

mekanism

Ett säkerhetsparadigm. De olika säkerhetsmekanismerna har olika typer och en eller flera nivåer av av dataskydd. Det här gäller säkerhetsmekanismer som stöds av GSS-API:t (Kerberos V5, offentlig RSA-nyckel osv).

säkerhetstjänst

Antingen skydd av personuppgifter eller integritet (eller ingen av dem). Integritetstjänsten är standard. Tjänsten är oberoende av mekanism.

QOP

QOP (Quality of Protection, skyddsegenskap). QOP anger vilken krypteringsalgoritm som ska användas för implementering av tjänsterna för integritet och skydd av personuppgifter. Alla säkerhetsmekanismer kan vara associerade med en eller flera QOP:er.

Program kan hämta listor med giltiga QOP:er och mekanismer genom funktioner i RPCSEC_GSS. (Läs "Diverse funktioner".) Utvecklarna bör undvika att använda mekanismer och QOP:er för hårdkodning i sina program så att programmen inte behöver ändras för att använda andra mekanismer och QOP:er.


Obs!

Från början betydde "säkerhetsalternativ" och "verifieringsalternativ" samma sak. Sedan introduktionen av RPCSEC_GSS har "alternativ" dock fått en något annorlunda innebörd. Nu kan ett alternativ omfatta en tjänst (integritet eller skydd av personuppgifter) förutom verifiering. Än så länge är det dock bara alternativet RPCSEC_GSS som gör det detta.


ONC-RPC-program använder RPCSEC_GSS för att upprätta säkra anslutningar med motparter, utväxla data och förstöra anslutningarna, på samma sätt som med andra alternativ. När en anslutning är upprättad kan programmet ändra QOP och tjänst för var och en av dataenheterna som skickas.

Mer information om RPCSEC_GSS, bl a om datatyper för RPCSEC_GSS, finns i direkthjälpsavsnittet (man page) rpcsec_gss(3N).

Rutiner för RPCSEC_GSS

Tabell 8-1 sammanfattar kommandon för RPCSEC_GSS. Det är avsett som en allmän översikt över funktioner i RPCSEC_GSS och går inte in i detalj på varje funktion. Du kan få mer information om en funktion genom att läsa direkthjälpsavsnittet (man page) för funktionen eller läsa direkthjälpsavsnittet rpcsec_gss(3N) för en översikt, bl a med en lista med datastrukturer för RPCSEC_GSS.

Tabell 8-1 Funktioner för RPCSEC_GSS
ÅtgärdFunktionIndataUtdata
 Skapa en säkerhetskontextrpc_gss_seccreate() KLIENT: hanterare, principalnamn, mekanism, QOP, tjänstetypAUTH-hanterare
 Ändra QOP, tjänstetyp för kontextrpc_gss_set_defaults() Gammal QOP, tjänst Ny QOP, tjänst
 Visa maximal storlek för data innan säkerhetsomvandlingrpc_gss_max_data_length() Maximal storlek för data som tillåts för transport Maximal storlek för data före omvandling.
 Visa maximal storlek för data innan säkerhetsomvandling rpc_gss_svc_max_data_length() Maximal storlek för data som tillåts för transport Maximal storlek för data före omvandling
 Ange namn på principal(er) som ska representeras av servernrpc_gss_set_svc_name() Principalnamn, RPC-program, version TRUE om det lyckas
 Hämta referenser för anropare (klient)rpc_gss_getcred()Pekare på svc_req-struktur UNIX-referenser, RPCSEC_GSS-referenser, cookie
 Ange (anges av användaren) callback-funktionrpc_gss_set_callback() Pekare på callback-funktion TRUE om det lyckas
 Skapa RPCSEC_GSS-struktur för principalnamn från unika parametrarrpc_gss_get_principal_name() Mekanism, användarnamn, systemnamn, domännamn Struktur för principalnamn för RPCSEC_GSS.
 Hämta en felkod när en rutin för RPCSEC_GSS misslyckasrpc_gss_get_error()   Felnummer för RPCSEC_GSS, errno, om det är tillämpligt
 Hämta strängar för alla installerade mekanismerrpc_gss_get_mechanisms()    Lista över giltiga mekanismer
 Hämta giltiga QOP-strängar < valign="top">Konvertera ASCII-mekanism till objektidentifierare för RPCrpc_gss_mech_to_oid() Mekanism (som sträng) Mekanism (som OID)
 Konvertera ASCII-QOP till heltalrpc_gss_qop_to_num() QOP (som sträng) QOP (som heltal)

Skapa en kontext

Kontexter skapas med anropet rpc_gss_seccreate(). Följande argument gäller för den här funktionen:

Den ger en AUTH -verifieringshanterare. Exempel 8-1 visar hur rpc_gss_seccreate() kan användas för att skapa en kontext med säkerhetsmekanismen Kerberos V5 och integritetstjänsten:


Exempel 8-1 rpc_gss_seccreate()

 CLIENT *clnt;                    /* klienthanterare */ 
char server_host[] = "foo"; 
char service_name[] = "nfs@eng.acme.com"; 
char mech[] = "kerberos_v5";  

clnt = clnt_create(server_host, SERVER_PROG, SERV_VERS, "nätsökväg"); 
clnt->clnt_auth = rpc_gss_seccreate(clnt, service_name, mech,                           rpc_gss_svc_integrity, NULL, NULL, NULL);

. . .

Följande är viktigt att tänka på för Exempel 8-1:

Mer information finns i direkthjälpsavsnittet (man page) rpc_gss_seccreate(3N).

Ändra värden och förstöra en kontext

När en kontext är angiven kan programmet behöva ändra QOP- och tjänstevärden för enstaka dataenheter som överförs. (Du kanske t ex vill att ett program ska kryptera ett lösenord, men inte ett användarnamn.) rpc_gss_set_defaults() gör att så blir fallet:


Exempel 8-2 rpc_gss_set_defaults()

rpc_gss_set_defaults(clnt->clnt_auth, rpc_gss_svc_privacy, qop);  

. . .

I det här fallet anges säkerhetstjänsten till "privacy" (se "Skapa en kontext"). qop är en pekare till en sträng som namnger den nya QOP:n.

Kontexter förstörs på det vanliga sättet med auth_destroy().

Mer information om hur du ändrar tjänst och QOP finns i direkthjälpsavsnittet (man page) rpc_gss_set_defaults(3N).

Principalnamn

Det krävs två typer av principalnamn för att upprätta och hantera en säkerhetskontext:

Ange principalnamn för servrar

En server måste få reda på namnen på de principaler som den ska representera när den startar. (Servern kan agera som fler än en principal.) rpc_gss_set_svc_name() anger namn för principalen/principalerna:


Exempel 8-3 rpc_gss_set_svc_name()

char *principal, *mechanism; 
u_int req_time;  

principal = "nfs@eng.acme.com"; 
mechanism = "kerberos_v5"; 
req_time = 10000;		/* tid under vilken referensen är giltig */ 

rpc_gss_set_svc_name(principal, mechanism, req_time, SERV_PROG, SERV_VERS);

(Kerberos ignorerar parametern req_time. Den kan användas av andra verifieringssystem.)

Mer information finns i direkthjälpsavsnittet (man page) rpc_gss_set_svc_name(3N).

Skapa principalnamn för klienter

Servrar måste kunna använda klienters principalnamn - t ex för att kontrollera om en klients principalnamn finns i en lista för åtkomstkontroll eller för att undersöka en UNIX-referens för klienten, om det finns en sådan referens. Sådana principalnamn anges med formen rpc_gss_principal_t strukturpekare. (Mer information om rpc_gss_principal_t finns i direkthjälpsavsnittet (man page) rpcsec_gss(3N).) Om en server vill jämföra ett mottaget principalnamn med namnet på ett känt element måste den skapa ett principalnamn med det formatet.

Anropet rpc_gss_get_principal_name() hanterar flera parametrar som indata, parametrar som identifierar en användare i ett nätverk, och skapar sedan ett principalnamn som en rpc_gss_principal_t-strukturpekare:


Exempel 8-4 rpc_gss_get_principal_name()

rpc_gss_principal_t *principal; 

rpc_gss_get_principal_name(principal, mekanism, namn, nod, domän); 
. . .

Argumenten för rpc_gss_get_principal_name() är:

Alla säkerhetsmekanismer kräver olika parametrar för identifiering. Kerberos V5 kräver t ex ett användarnamn och, valfritt, fullständiga namn för en nod och en domän (namn för värd och användarkategori med Kerberos-terminologi).

Mer information finns i direkthjälpsavsnittet (man page) rpc_gss_get_principal_name(3N).

Frigöra principalnamn

Du frigör principalnamn med biblioteksanropet free().

Ta emot referenser på servern

Servern måste kunna hämta klientens referenser. Med funktionen rpc_gss_getcred(), vilken visas i Exempel 8-5, kan servern hämta antingen UNIX-referenser eller RPCSEC_GSS-referenser (eller både och). Den gör det via två argument som anges om funktionen lyckas. Ett av argumenten är en pekare till en rpc_gss_ucred_t-struktur, som innehåller anroparens UNIX-referenser, om det finns sådana:

typedef struct {
    uid_t   uid;          /* användar-ID */ 
    gid_t   gid;          /* grupp-ID */ 
    short   gidlen; 
    git_t   *gidlist;     /* lista över grupper */ 
} rpc_gss_ucred_t;

Det andra argumentet är en pekare till en rpc_gss_raw_cred_t-struktur, som ser ut så här:

typedef struct { 
		u_int                  version;          /* programversion för RPCSEC_GSS */ 
		char                   *mekanism; 
		char                   *qop; 
		rpc_gss_principal_t    client_principal; /* principalnamn för klienten */ 
		char                   *svc_principal;	 /* principalnamn för servern */ 
		rpc_gss_service_t      tjänst;	         /* privacy, integrity enum */ 
} rpc_gss_rawcred_t;  
(I "Skapa principalnamn för klienter" finns en beskrivning av strukturen rpc_gss_principal_t och hur den skapas.) Eftersom rpc_gss_rawcred_t innehåller både klientens och serverns principalnamn kan rpc_gss_getcred() returnera båda.

Exempel 8-5 är ett exempel på en enkel klareringsprocedur på servern, där servern tar emot referenserna för anroparen. Proceduren hämtar anroparens UNIX-referenser och verifierar sedan användarens identitet med hjälp av mekanismen, QOP:en och tjänstetypen i argumentet rpc_gss_rcred_t.


Exempel 8-5 Hämta referenser

static void server_prog(struct svc_req *rqstp, SVCXPRT *xprt) 
{
 		rpc_gss_ucred_t *ucred; 
		rpc_gss_rawcred_t *rcred; 
 		if (rqst->rq_proq == NULLPROC) { 
			svc_sendreply(xprt, xdr_void, NULL); 
			return; 
		} 
		/* 
		 * verifiera alla andra förfrågningar 
 		 */ 
 		switch (rqstp->rq_cred.oa_flavor) { 
		case RPCSEC_GSS: 
			/* 
			 * hämta referensinformation 
			 */ 
			rpc_gss_getcred(rqstp, &rcred, &ucred, NULL); 
			/* 
			* verifiera att användaren får ansluta 
			* med hjälp av mottagna säkerhetsparametrar 
			* från min konfigurationsfil 
			*/ 
			if (!authenticate_user(ucred->uid, rcred->mechanism, 
				rcred->qop, rcred->service)) { 
				svcerr_weakauth(xprt); 
				return; 
			} 
			break; 	/* tillåt användaren i */ 
		default: 
			svcerr_weakauth(xprt); 
			return; 
		} /* avsluta växel */ 
 
		switch (rqstp->rq_proq) { 
		case SERV_PROC1: 
			. . . 
		}  

		/* vanlig behandling av förfrågan; skicka svar ... */ 

 		return;  

}

Mer information finns i direkthjälpsavsnittet (man page) rpc_gss_getcred(3N).

Cookies

I Exempel 8-5 är det sista argumentet för rpc_gss_getcred() (här ett NULL-värde) en användardefinierad cookie, vars returnerade värde kommer att vara det som angavs av servern när kontexten upprättades. Den här cookien, ett fyra byte stort värde, kan användas på valfritt sätt för programmet - RPC tolkar inte värdet. Cookien kan t ex vara en pekare eller ett index för en struktur som representerar den som upprättade kontexten. I stället för att det här värdet beräknas för varje förfrågan beräknas det vid den tidpunkt då kontexten upprättas (vilket minskar tiden som krävs för behandling av förfrågningar).

Callback-funktioner

Cookies kan även användas med callback-funktioner. Genom att använda funktionen rpc_gss_set_callback() kan en server ange en (användardefinierad) callback-funktion så att den vet när en kontext används för första gången. Callback-funktionen anropas första gången en kontext används för datautbyte, efter att kontexten har upprättats för det angivna programmet och versionen.

Den användardefinierade callback-funktionen anges med följande format:

De andra och tredje argumenten, deleg och gss_context, är GSS-API-datatyper som för närvarande inte används och därför kan de ignoreras av callback-funktionen. (I korthet är deleg identiteten för valfri delegerad jämlike, medan gss_context är en pekare till GSS-API-kontexten som kan användas om programmet behöver utföra GSS-API-åtgärder i kontexten - dvs, för att testa villkor för accepterande.) Argumentet cookie beskrivs tidigare i det här avsnittet.

Argumentet lock är en pekare till en rpc_gss_lock_t-struktur:

typedef struct { 
		bool_t              locked; 
		rpc_gss_rawcred_t   *raw_cred; 
} rpc_gss_lock_t;
Den här parametern gör att en server kan använda en särskild QOP och tjänst för sessionen. QOP:n och tjänsten i strukturen rpc_gss_rawcred_t beskrivs i Exempel 8-5. (Servern bör inte ändra värdena för tjänst och QOP.) När den användardefinierade callback-funktionen anropas anges fältet locked till FALSE. Om servern anger locked till TRUE kommer förfrågningar med värden för QOP och tjänst som matchar värdena i strukturen rpc_gss_rawcred_t att accepteras.

Mer information finns i direkthjälpsavsnittet (man page) rpc_gss_set_callback(3N).

Maximal datastorlek

Två funktioner - rpc_gss_max_data_length() och rpc_gss_svc_max_data_length() - används för att avgöra hur stort ett stycke data kan vara innan det omvandlas av säkerhetsfunktioner och skickas vidare. En säkerhetsomvandling, t ex kryptering, ändrar vanligen storleken på ett stycke överförd data (oftast förstoras stycket). För att se till att data inte förstoras så mycket att den inte går att använda, returnerar dessa två funktioner - den förra för klienten, den senare för servern- maximal storlek före omvandlingen för en given transport.

Mer information finns i direkthjälpsavsnitten (man pages) rpc_gss_max_data_length(3N) och rpc_gss_svc_max_data_length(3N).

Diverse funktioner

De finns flera funktioner som du kan använda för att hämta information om det installerade säkerhetssystemet:

Om programmeraren använder de här funktionerna kan hårdkodade säkerhetsparametrar undvikas i program. (En lista över alla RPCSEC_GSS-funktioner finns i Tabell 8-1 och i direkthjälpsavsnittet (man page) rpcsec_gss(3N).)

Associerade filer

RPCSEC_GSS använder vissa filer för lagring av information.

Tabellen gsscred

När en server tar emot en klients referenser som hör till en förfrågan, tar servern antingen emot klientens principalnamn (i form av en pekare för en rpc_gss_principal_t-struktur) eller klientens lokala UNIX-referenser (UID, användar-ID). Tjänster som NFS kräver en lokal UNIX-referens för åtkomstkontroll, men andra tjäsnter kanske inte gör det - de kan t ex lagra principalnamnet som en rpc_gss_principal_t-struktur direkt i sina egna listor för åtkomstkontroll.


Obs!

Matchningen av en klients nätverksreferens (dess principalnamn) och lokala UNIX-referenser sker inte automatiskt - den måste uttryckligen anges av den lokala säkerhetsadministratören.


Filen gsscred innehåller både klientens UNIX- och nätverksreferenser (t ex Kerberos V5). (Den senare är Hex-ASCII-motsvarigheten för strukturen rpc_gss_principal_t.) Åtkomsten till filen sker via XFN och därför kan den här tabellen implementeras för filer, NIS eller NIS+, eller valfri kommande namntjänst som stöds av XFN. I XFN-hierarkin visas den här tabellen som this_org_unit/tjänst/gsscred. Tabellen gsscred underhålls med hjälp av gsscred-verktyget, som kan användas av administratörer för att lägga till och ta bort användare och mekanismer.

/etc/gss/qop och /etc/gss/mech

För enkelhets skull använder RPCSEC_GSS strängliteraler för att representera mekanismer och QOP-parametrar (Quality of Protection). Själva de underliggande mekanismerna kräver däremot att mekanismerna representeras som objektidentifierare och QOP:er som 32-bitars heltal. Dessutom måste det delade bibliotek som implementerar tjänsterna för mekanismen anges för varje mekanism.

Filen /etc/gss/mech innehåller följande information om alla installerade mekanismer i systemet: mekanismens namn, i ASCII; mekanismens OID; det delade bibliotek som implementerar tjänsterna som tillhandahålls av mekanismen; och, valfritt, kärnmodulen som implementerar tjänsten. Ett exempel kan se ut så här:


kerberos_v5   1.2.840.113554.1.2.2    gl/mech_krb5.so gl_kmech_krb5

Filen /etc/gss/qop innehåller alla QOP:er som stöds av alla installerade mekanismer, både som ASCII-strängar och 32-bitars heltal.

Både /etc/gss/mech och /etc/gss/qop skapas när en säkerhetsmekanism installeras för första gången i ett system.

Eftersom många RPC-rutiner inom kärnan använder värden som inte är strängar för att representera mekanism och QOP, kan program använda funktionerna rpc_gss_mech_to_oid() och rpc_gss_qop_to_num() för att hämta värden för dessa parametrar, om programmen behöver använda dessa rutiner inom kärnan.