afpfs-ng-mac/lib/users.c

154 lines
3.6 KiB
C

#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include "afpfs-ng/afp.h"
#include "afpfs-ng/map_def.h"
/* How mapping works
*
* There are 3 kinds of user/group mapping:
*
* 1. Common user directory
*
* This is where the client and server share the same user/group database.
* An example of this is where NIS is used.
*
* 2. Login ids
*
* This is where all the files appear as the user that logged in. This would
* typically be used where the databases are separate, and one user expects to
* be able to read/write all the files he sees. This can get confusing, since
* any files that aren't his will appear to be owned by him, but writing to
* them will result in an EPERM.
*
* 3. Name mapped
*
* All the uid/gid translation is done based on usernames.
*
* This is currently unsupported.
*
*/
int translate_uidgid_to_server(struct afp_volume * volume,
unsigned int * newuid, unsigned int *newgid)
{
switch(volume->mapping) {
case AFP_MAPPING_COMMON:
/* The user databases are the same, don't do
* any translaion. */
break;
case AFP_MAPPING_LOGINIDS:
/* Return the value of what we used when we
logged in.*/
*newuid=volume->server->server_uid;
*newgid=volume->server->server_gid;
break;
default:
case AFP_MAPPING_UNKNOWN:
return -1;
break;
}
return 0;
}
int translate_uidgid_to_client(struct afp_volume * volume,
unsigned int * newuid, unsigned int *newgid)
{
switch(volume->mapping) {
case AFP_MAPPING_COMMON:
/* The user databases are the same, don't do
* any translaion. */
break;
case AFP_MAPPING_LOGINIDS:
/* This is the case where we always return the uid/gid
* of the user who ran afpfsd.
*/
*newuid=volume->server->passwd.pw_uid;
*newgid=volume->server->passwd.pw_gid;
break;
default:
case AFP_MAPPING_UNKNOWN:
return -1;
break;
}
return 0;
}
int afp_detect_mapping(struct afp_volume * volume)
{
char name[255];
struct passwd * passwd_entry;
unsigned int dummy;
unsigned int tmpgid;
/* See if it is already set. This is typically when the client
* requested a specific mapping. */
if (volume->mapping != AFP_MAPPING_UNKNOWN)
return 0;
if ((volume->attributes & kNoNetworkUserIDs) ) {
volume->mapping = AFP_MAPPING_LOGINIDS;
return 0;
}
/* Check to see if the user databases appear to be synchronous.
* This is done based on the algorithm specified on p.20.
*/
/* By default, we're in AFP_MAPPING_LOGINIDS. */
volume->mapping = AFP_MAPPING_LOGINIDS;
volume->server->server_gid_valid=0;
/* 1. call getuid */
passwd_entry=&volume->server->passwd;
/* 2. Send FPGetUserInfo to get the user's uid */
if (afp_getuserinfo(volume->server, 1, /* this user */
0, /* Irrelevant since we're getting the info for ThisUser */
kFPGetUserInfo_USER_ID,
&volume->server->server_uid,
&dummy))
return 0;
/* In the past, this has not worked for some versions of Mac OS, but
* this hasn't been fully verified */
if (afp_getuserinfo(volume->server, 1, /* this user */
0,
kFPGetUserInfo_PRI_GROUPID, &dummy,
&tmpgid)==0) {
volume->server->server_gid_valid=1;
volume->server->server_gid=tmpgid;
}
/* 3. If they match, call getpwuid to get the local user name */
if (volume->server->server_uid!=passwd_entry->pw_uid)
return 0;
/* 4. send an FPMapID to get the user's username. */
afp_mapid(volume->server,
(volume->attributes & kSupportsUTF8Names)
? kUserIDToUTF8Name : kUserIDToName,
passwd_entry->pw_uid,name);
/* 5. If they match, we're in AFP_MAPPING_COMMON mode. */
if (strcmp(name,passwd_entry->pw_name)==0)
volume->mapping = AFP_MAPPING_COMMON;
return 0;
}