diff options
Diffstat (limited to 'nscd/connections.c')
-rw-r--r-- | nscd/connections.c | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/nscd/connections.c b/nscd/connections.c index ca139fbddf..3f05d685ef 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -195,7 +195,7 @@ close_sockets (void) /* Handle new request. */ static void -handle_request (int fd, request_header *req, void *key) +handle_request (int fd, request_header *req, void *key, uid_t uid) { if (debug_level > 0) dbg_log (_("handle_request: request received (Version = %d)"), @@ -251,7 +251,7 @@ cannot handle old request version %d; current version is %d"), /* See whether we can handle it from the cache. */ cached = (struct hashentry *) cache_search (req->type, key, req->key_len, - db); + db, uid); if (cached != NULL) { /* Hurray it's in the cache. */ @@ -279,35 +279,35 @@ cannot handle old request version %d; current version is %d"), switch (req->type) { case GETPWBYNAME: - addpwbyname (&dbs[serv2db[req->type]], fd, req, key); + addpwbyname (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETPWBYUID: - addpwbyuid (&dbs[serv2db[req->type]], fd, req, key); + addpwbyuid (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETGRBYNAME: - addgrbyname (&dbs[serv2db[req->type]], fd, req, key); + addgrbyname (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETGRBYGID: - addgrbygid (&dbs[serv2db[req->type]], fd, req, key); + addgrbygid (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETHOSTBYNAME: - addhstbyname (&dbs[serv2db[req->type]], fd, req, key); + addhstbyname (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETHOSTBYNAMEv6: - addhstbynamev6 (&dbs[serv2db[req->type]], fd, req, key); + addhstbynamev6 (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETHOSTBYADDR: - addhstbyaddr (&dbs[serv2db[req->type]], fd, req, key); + addhstbyaddr (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETHOSTBYADDRv6: - addhstbyaddrv6 (&dbs[serv2db[req->type]], fd, req, key); + addhstbyaddrv6 (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETSTAT: @@ -315,7 +315,24 @@ cannot handle old request version %d; current version is %d"), break; case SHUTDOWN: - termination_handler (0); + /* Accept shutdown only from root */ + if (secure_in_use && uid == 0) + termination_handler (0); + else + { + struct ucred caller; + int optlen = sizeof (caller); + + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0) + { + char buf[256]; + + dbg_log (_("error getting callers id: %s"), + strerror_r (errno, buf, sizeof (buf))); + } + else if (caller.uid == 0) + termination_handler (0); + } break; default: @@ -362,6 +379,7 @@ nscd_run (void *p) int fd = accept (conn.fd, NULL, NULL); request_header req; char buf[256]; + uid_t uid = 0; if (fd < 0) { @@ -380,6 +398,25 @@ nscd_run (void *p) continue; } + if (secure_in_use) + { + struct ucred caller; + int optlen = sizeof (caller); + + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, + &caller, &optlen) < 0) + { + dbg_log (_("error getting callers id: %s"), + strerror_r (errno, buf, sizeof (buf))); + close (fd); + continue; + } + + if (req.type < GETPWBYNAME || req.type >= LASTREQ + || secure[serv2db[req.type]]) + uid = caller.uid; + } + /* It should not be possible to crash the nscd with a silly request (i.e., a terribly large key. We limit the size to 1kb. */ @@ -404,7 +441,7 @@ nscd_run (void *p) } /* Phew, we got all the data, now process it. */ - handle_request (fd, &req, keybuf); + handle_request (fd, &req, keybuf, uid); /* We are done. */ close (fd); |