Magellan Linux

Diff of /trunk/mkinitrd-magellan/klibc/usr/kinit/nfsmount/dummypmap.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 814 by niro, Sat Sep 1 22:45:15 2007 UTC revision 815 by niro, Fri Apr 24 18:32:46 2009 UTC
# Line 15  Line 15 
15  #include <string.h>  #include <string.h>
16  #include <sys/socket.h>  #include <sys/socket.h>
17    
18    #include "dummypmap.h"
19  #include "sunrpc.h"  #include "sunrpc.h"
20    
21  extern const char *progname;  extern const char *progname;
22    
23  struct portmap_call {  struct portmap_args {
  struct rpc_call rpc;  
24   uint32_t program;   uint32_t program;
25   uint32_t version;   uint32_t version;
26   uint32_t proto;   uint32_t proto;
27   uint32_t port;   uint32_t port;
28  };  };
29    
30    struct portmap_call {
31     struct rpc_call rpc;
32     struct portmap_args args;
33    };
34    
35  struct portmap_reply {  struct portmap_reply {
36   struct rpc_reply rpc;   struct rpc_reply rpc;
37   uint32_t port;   uint32_t port;
# Line 66  static const char *protoname(uint32_t pr Line 71  static const char *protoname(uint32_t pr
71   }   }
72  }  }
73    
74    static void * get_auth(struct rpc_auth *auth)
75    {
76     switch (ntohl(auth->flavor)) {
77     case AUTH_NULL:
78     /* Fallthrough */
79     case AUTH_UNIX:
80     return (char *)&auth->body + ntohl(auth->len);
81     default:
82     return NULL;
83     }
84    }
85    
86    static int check_unix_cred(struct rpc_auth *cred)
87    {
88     uint32_t len;
89     int quad_len;
90     uint32_t node_name_len;
91     int quad_name_len;
92     uint32_t *base;
93     uint32_t *pos;
94     int ret = -1;
95    
96     len = ntohl(cred->len);
97     quad_len = (len + 3) >> 2;
98     if (quad_len < 6)
99     /* Malformed creds */
100     goto out;
101    
102     base = pos = cred->body;
103    
104     /* Skip timestamp */
105     pos++;
106    
107     /* Skip node name: only localhost can succeed. */
108     node_name_len = ntohl(*pos++);
109     quad_name_len = (node_name_len + 3) >> 2;
110     if (pos + quad_name_len + 3 > base + quad_len)
111     /* Malformed creds */
112     goto out;
113     pos += quad_name_len;
114    
115     /* uid must be 0 */
116     if (*pos++ != 0)
117     goto out;
118    
119     /* gid must be 0 */
120     if (*pos++ != 0)
121     goto out;
122    
123     /* Skip remaining gids */
124     ret = 0;
125    
126    out:
127     return ret;
128    }
129    
130    static int check_cred(struct rpc_auth *cred)
131    {
132     switch (ntohl(cred->flavor)) {
133     case AUTH_NULL:
134     return 0;
135     case AUTH_UNIX:
136     return check_unix_cred(cred);
137     default:
138     return -1;
139     }
140    }
141    
142    static int check_vrf(struct rpc_auth *vrf)
143    {
144     return (vrf->flavor == htonl(AUTH_NULL)) ? 0 : -1;
145    }
146    
147  static int dummy_portmap(int sock, FILE *portmap_file)  static int dummy_portmap(int sock, FILE *portmap_file)
148  {  {
149   struct sockaddr_in sin;   struct sockaddr_in sin;
150   int pktlen, addrlen;   int pktlen, addrlen;
151   union {   unsigned char pkt[65536]; /* Max UDP packet size */
152   struct portmap_call c;   /* RPC UDP packets do not include TCP fragment size */
153   unsigned char b[65536]; /* Max UDP packet size */   struct rpc_call *rpc = (struct rpc_call *) &pkt[-4];
154   } pkt;   struct rpc_auth *cred;
155     struct rpc_auth *vrf;
156     struct portmap_args *args;
157   struct portmap_reply rply;   struct portmap_reply rply;
158    
159   for (;;) {   for (;;) {
160   addrlen = sizeof sin;   addrlen = sizeof sin;
161   pktlen = recvfrom(sock, &pkt.c.rpc.hdr.udp, sizeof pkt, 0,   pktlen = recvfrom(sock, &pkt, sizeof pkt, 0,
162    (struct sockaddr *)&sin, &addrlen);    (struct sockaddr *)&sin, &addrlen);
163    
164   if (pktlen < 0) {   if (pktlen < 0) {
# Line 92  static int dummy_portmap(int sock, FILE Line 172  static int dummy_portmap(int sock, FILE
172   if (pktlen + 4 < sizeof(struct portmap_call))   if (pktlen + 4 < sizeof(struct portmap_call))
173   continue; /* Bad packet */   continue; /* Bad packet */
174    
175   if (pkt.c.rpc.hdr.udp.msg_type != htonl(RPC_CALL))   if (rpc->hdr.udp.msg_type != htonl(RPC_CALL))
176   continue; /* Bad packet */   continue; /* Bad packet */
177    
178   memset(&rply, 0, sizeof rply);   memset(&rply, 0, sizeof rply);
179    
180   rply.rpc.hdr.udp.xid = pkt.c.rpc.hdr.udp.xid;   rply.rpc.hdr.udp.xid = rpc->hdr.udp.xid;
181   rply.rpc.hdr.udp.msg_type = htonl(RPC_REPLY);   rply.rpc.hdr.udp.msg_type = htonl(RPC_REPLY);
182    
183   if (pkt.c.rpc.rpc_vers != htonl(2)) {   cred = (struct rpc_auth *) &rpc->cred_flavor;
184     if (rpc->rpc_vers != htonl(2)) {
185   rply.rpc.reply_state = htonl(REPLY_DENIED);   rply.rpc.reply_state = htonl(REPLY_DENIED);
186   /* state <- RPC_MISMATCH == 0 */   /* state <- RPC_MISMATCH == 0 */
187   } else if (pkt.c.rpc.program != htonl(PORTMAP_PROGRAM)) {   } else if (rpc->program != htonl(PORTMAP_PROGRAM)) {
188   rply.rpc.reply_state = htonl(PROG_UNAVAIL);   rply.rpc.reply_state = htonl(PROG_UNAVAIL);
189   } else if (pkt.c.rpc.prog_vers != htonl(2)) {   } else if (rpc->prog_vers != htonl(2)) {
190   rply.rpc.reply_state = htonl(PROG_MISMATCH);   rply.rpc.reply_state = htonl(PROG_MISMATCH);
191   } else if (pkt.c.rpc.cred_len != 0 || pkt.c.rpc.vrf_len != 0) {   } else if (!(vrf = get_auth(cred)) ||
192       (char *)vrf > (char *)pkt + pktlen - 8 - sizeof(*args) ||
193       !(args = get_auth(vrf)) ||
194       (char *)args > (char *)pkt + pktlen - sizeof(*args) ||
195       check_cred(cred) || check_vrf(vrf)) {
196   /* Can't deal with credentials data; the kernel   /* Can't deal with credentials data; the kernel
197     won't send them */     won't send them */
198   rply.rpc.reply_state = htonl(SYSTEM_ERR);   rply.rpc.reply_state = htonl(SYSTEM_ERR);
199   } else {   } else {
200   switch (ntohl(pkt.c.rpc.proc)) {   switch (ntohl(rpc->proc)) {
201   case PMAP_PROC_NULL:   case PMAP_PROC_NULL:
202   break;   break;
203   case PMAP_PROC_SET:   case PMAP_PROC_SET:
204   if (pkt.c.proto == htonl(IPPROTO_TCP) ||   if (args->proto == htonl(IPPROTO_TCP) ||
205      pkt.c.proto == htonl(IPPROTO_UDP)) {      args->proto == htonl(IPPROTO_UDP)) {
206   if (portmap_file)   if (portmap_file)
207   fprintf(portmap_file,   fprintf(portmap_file,
208   "%u %u %s %u\n",   "%u %u %s %u\n",
209   ntohl(pkt.c.program),   ntohl(args->program),
210   ntohl(pkt.c.version),   ntohl(args->version),
211   protoname(pkt.c.proto),   protoname(args->proto),
212   ntohl(pkt.c.port));   ntohl(args->port));
213   rply.port = htonl(1); /* TRUE = success */   rply.port = htonl(1); /* TRUE = success */
214   }   }
215   break;   break;

Legend:
Removed from v.814  
changed lines
  Added in v.815