2022-02-12 01:30:50 +03:00
|
|
|
// Copyright (c) Vitaliy Filippov, 2019+
|
|
|
|
// License: VNPL-1.1 (see README.md for details)
|
|
|
|
//
|
|
|
|
// Portmap service for NFS proxy
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "nfs/portmap.h"
|
|
|
|
#include "nfs/xdr_impl_inline.h"
|
|
|
|
|
|
|
|
#include "malloc_or_die.h"
|
|
|
|
#include "nfs_portmap.h"
|
|
|
|
#include "sha256.h"
|
2022-07-31 01:12:37 +03:00
|
|
|
#include "str_util.h"
|
2022-02-12 01:30:50 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The NULL procedure. All protocols/versions must provide a NULL procedure
|
|
|
|
* as index 0.
|
|
|
|
* It is used by clients, and rpcinfo, to "ping" a service and verify that
|
|
|
|
* the service is available and that it does support the indicated version.
|
|
|
|
*/
|
|
|
|
static int pmap2_null_proc(struct rpc_context *rpc, rpc_op_t *rop)
|
|
|
|
{
|
|
|
|
rpc_queue_reply(rop);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* v2 GETPORT.
|
|
|
|
* This is the lookup function for portmapper version 2.
|
|
|
|
* A client provides program, version and protocol (tcp or udp)
|
|
|
|
* and portmapper returns which port that service is available on,
|
|
|
|
* (or 0 if no such program is registered.)
|
|
|
|
*/
|
|
|
|
static int pmap2_getport_proc(portmap_service_t *self, rpc_op_t *rop)
|
|
|
|
{
|
|
|
|
PMAP2GETPORTargs *args = (PMAP2GETPORTargs *)rop->request;
|
|
|
|
uint32_t *reply = (uint32_t *)rop->reply;
|
|
|
|
auto it = self->reg_ports.lower_bound((portmap_id_t){
|
|
|
|
.prog = args->prog,
|
|
|
|
.vers = args->vers,
|
|
|
|
.udp = args->prot == IPPROTO_UDP,
|
|
|
|
.ipv6 = false,
|
|
|
|
});
|
|
|
|
if (it != self->reg_ports.end() &&
|
|
|
|
it->prog == args->prog && it->vers == args->vers &&
|
|
|
|
it->udp == (args->prot == IPPROTO_UDP))
|
|
|
|
{
|
|
|
|
*reply = it->port;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*reply = 0;
|
|
|
|
}
|
|
|
|
rpc_queue_reply(rop);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* v2 DUMP.
|
|
|
|
* This RPC returns a list of all endpoints that are registered with
|
|
|
|
* portmapper.
|
|
|
|
*/
|
|
|
|
static int pmap2_dump_proc(portmap_service_t *self, rpc_op_t *rop)
|
|
|
|
{
|
|
|
|
pmap2_mapping_list *list = (pmap2_mapping_list*)malloc_or_die(sizeof(pmap2_mapping_list) * self->reg_ports.size());
|
|
|
|
xdr_add_malloc(rop->xdrs, list);
|
|
|
|
PMAP2DUMPres *reply = (PMAP2DUMPres *)rop->reply;
|
|
|
|
int i = 0;
|
|
|
|
for (auto it = self->reg_ports.begin(); it != self->reg_ports.end(); it++)
|
|
|
|
{
|
|
|
|
if (it->ipv6)
|
|
|
|
continue;
|
|
|
|
list[i] = {
|
|
|
|
.map = {
|
|
|
|
.prog = it->prog,
|
|
|
|
.vers = it->vers,
|
|
|
|
.prot = it->udp ? IPPROTO_UDP : IPPROTO_TCP,
|
|
|
|
.port = it->port,
|
|
|
|
},
|
|
|
|
.next = list+i+1,
|
|
|
|
};
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
list[i-1].next = NULL;
|
|
|
|
// Send reply
|
|
|
|
reply->list = list;
|
|
|
|
rpc_queue_reply(rop);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* v3 GETADDR.
|
|
|
|
* This is the lookup function for portmapper version 3.
|
|
|
|
*/
|
|
|
|
static int pmap3_getaddr_proc(portmap_service_t *self, rpc_op_t *rop)
|
|
|
|
{
|
|
|
|
PMAP3GETADDRargs *args = (PMAP3GETADDRargs *)rop->request;
|
|
|
|
PMAP3GETADDRres *reply = (PMAP3GETADDRres *)rop->reply;
|
|
|
|
portmap_id_t ref = (portmap_id_t){
|
|
|
|
.prog = args->prog,
|
|
|
|
.vers = args->vers,
|
|
|
|
.udp = args->netid == "udp" || args->netid == "udp6",
|
|
|
|
.ipv6 = args->netid == "tcp6" || args->netid == "udp6",
|
|
|
|
};
|
|
|
|
auto it = self->reg_ports.lower_bound(ref);
|
|
|
|
if (it != self->reg_ports.end() &&
|
|
|
|
it->prog == ref.prog && it->vers == ref.vers &&
|
|
|
|
it->udp == ref.udp && it->ipv6 == ref.ipv6)
|
|
|
|
{
|
|
|
|
reply->addr = xdr_copy_string(rop->xdrs, it->addr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
reply->addr = {};
|
|
|
|
}
|
|
|
|
rpc_queue_reply(rop);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* v3 DUMP.
|
|
|
|
* This RPC returns a list of all endpoints that are registered with
|
|
|
|
* portmapper.
|
|
|
|
*/
|
|
|
|
static std::string netid_udp = "udp";
|
|
|
|
static std::string netid_udp6 = "udp6";
|
|
|
|
static std::string netid_tcp = "tcp";
|
|
|
|
static std::string netid_tcp6 = "tcp6";
|
|
|
|
static int pmap3_dump_proc(portmap_service_t *self, rpc_op_t *rop)
|
|
|
|
{
|
|
|
|
PMAP3DUMPres *reply = (PMAP3DUMPres *)rop->reply;
|
2022-05-10 12:26:47 +03:00
|
|
|
pmap3_mapping_list *list = (pmap3_mapping_list*)malloc_or_die(sizeof(pmap3_mapping_list*) * self->reg_ports.size());
|
2022-02-12 01:30:50 +03:00
|
|
|
xdr_add_malloc(rop->xdrs, list);
|
|
|
|
int i = 0;
|
|
|
|
for (auto it = self->reg_ports.begin(); it != self->reg_ports.end(); it++)
|
|
|
|
{
|
|
|
|
list[i] = (pmap3_mapping_list){
|
|
|
|
.map = (pmap3_mapping){
|
|
|
|
.prog = it->prog,
|
|
|
|
.vers = it->vers,
|
|
|
|
.netid = xdr_copy_string(rop->xdrs, it->ipv6
|
|
|
|
? (it->udp ? netid_udp6 : netid_tcp6)
|
|
|
|
: (it->udp ? netid_udp : netid_tcp)),
|
|
|
|
.addr = xdr_copy_string(rop->xdrs, it->addr), // 0.0.0.0.port
|
|
|
|
.owner = xdr_copy_string(rop->xdrs, it->owner),
|
|
|
|
},
|
|
|
|
.next = list+i+1,
|
|
|
|
};
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
list[i-1].next = NULL;
|
|
|
|
reply->list = list;
|
|
|
|
rpc_queue_reply(rop);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
portmap_service_t::portmap_service_t()
|
|
|
|
{
|
|
|
|
struct rpc_service_proc_t pt[] = {
|
|
|
|
{PMAP_PROGRAM, PMAP_V2, PMAP2_NULL, (rpc_handler_t)pmap2_null_proc, NULL, 0, NULL, 0, this},
|
|
|
|
{PMAP_PROGRAM, PMAP_V2, PMAP2_GETPORT, (rpc_handler_t)pmap2_getport_proc, (xdrproc_t)xdr_PMAP2GETPORTargs, sizeof(PMAP2GETPORTargs), (xdrproc_t)xdr_u_int, sizeof(u_int), this},
|
|
|
|
{PMAP_PROGRAM, PMAP_V2, PMAP2_DUMP, (rpc_handler_t)pmap2_dump_proc, NULL, 0, (xdrproc_t)xdr_PMAP2DUMPres, sizeof(PMAP2DUMPres), this},
|
|
|
|
{PMAP_PROGRAM, PMAP_V3, PMAP3_NULL, (rpc_handler_t)pmap2_null_proc, NULL, 0, NULL, 0, this},
|
|
|
|
{PMAP_PROGRAM, PMAP_V3, PMAP3_GETADDR, (rpc_handler_t)pmap3_getaddr_proc, (xdrproc_t)xdr_PMAP3GETADDRargs, sizeof(PMAP3GETADDRargs), (xdrproc_t)xdr_string, sizeof(xdr_string_t), this},
|
|
|
|
{PMAP_PROGRAM, PMAP_V3, PMAP3_DUMP, (rpc_handler_t)pmap3_dump_proc, NULL, 0, (xdrproc_t)xdr_PMAP3DUMPres, sizeof(PMAP3DUMPres), this},
|
|
|
|
};
|
|
|
|
for (int i = 0; i < sizeof(pt)/sizeof(pt[0]); i++)
|
|
|
|
{
|
|
|
|
proc_table.push_back(pt[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string sha256(const std::string & str)
|
|
|
|
{
|
|
|
|
std::string hash;
|
|
|
|
hash.resize(32);
|
|
|
|
SHA256_CTX ctx;
|
|
|
|
sha256_init(&ctx);
|
|
|
|
sha256_update(&ctx, (uint8_t*)str.data(), str.size());
|
|
|
|
sha256_final(&ctx, (uint8_t*)hash.data());
|
|
|
|
return hash;
|
|
|
|
}
|