Skip to content

Instantly share code, notes, and snippets.

@luqmana
Created May 2, 2014 05:15
Show Gist options
  • Save luqmana/4df1b8a6e10c3f76e0e0 to your computer and use it in GitHub Desktop.
Save luqmana/4df1b8a6e10c3f76e0e0 to your computer and use it in GitHub Desktop.
#![feature(phase)]
extern crate libc;
extern crate regex;
#[phase(syntax)]
extern crate regex_macros;
use libc::{c_char, c_int, c_ushort};
use std::io::{Acceptor, Listener};
use std::io::{BufferedStream, TcpListener, TcpStream};
use std::str;
#[link(name = "identd_procfs")]
extern {
fn lport_to_uid(port: c_ushort) -> c_int;
}
extern {
fn getpwuid(uid: c_int) -> *passwd;
}
#[allow(non_camel_case_types)]
struct passwd {
pw_name: *c_char,
pw_passd: *c_char,
pw_uid: c_int,
pw_gid: c_int,
pw_gecox: *c_char,
pw_dir: *c_char,
pw_shell: *c_char
}
fn handle_client(mut sock: TcpStream) {
println!("Connection from {}.", sock.peer_name().unwrap());
// So let's read in the request from the client
let ref mut sock = BufferedStream::new(sock);
let req = match sock.read_line() {
Ok(buf) => buf,
Err(e) => {
println!("Couldn't read from stream: {}.", e);
return;
}
};
// Now we match against a regex for the right format
let r = regex!("(?P<sport>[0-9]+)[ ]*,[ ]*(?P<cport>[0-9]+)");
// Does the input match?
match r.captures(req) {
Some(caps) => {
// Yes it does! Let's get the parts we want
let sport: c_ushort = from_str(caps.name("sport")).unwrap();
let cport: c_ushort = from_str(caps.name("cport")).unwrap();
// Now let's find the user
let uid = unsafe { lport_to_uid(sport) };
if uid == -1 {
println!("Couldn't find user mapped to port: {}.", sport);
let _ = write!(sock, "{}, {} : ERROR : NO-USER", sport, cport);
return;
}
let p = unsafe { getpwuid(uid) };
if p.is_null() {
println!("Couldn't map uid ({}) to passwd entry.", uid);
let _ = write!(sock, "{}, {} : ERROR : UNKNOWN-ERROR", sport, cport);
return;
}
let name = unsafe {
str::raw::from_c_str((*p).pw_name)
};
// and write out the response, done!
let _ = write!(sock, "{}, {} : USERID : UNIX : {}", sport, cport, name);
}
None => println!("Received badly formatted request.")
}
}
fn main() {
let addr = from_str("0.0.0.0:113").unwrap();
let mut acceptor = match TcpListener::bind(addr).listen() {
Ok(acceptor) => acceptor,
Err(e) => fail!("Couldn't listen on {}: {}.", addr, e)
};
println!("Listening on {}.", addr);
for stream in acceptor.incoming() {
match stream {
Ok(s) => spawn(proc() handle_client(s)),
Err(e) => println!("Couldn't accept connection: {}.", e)
}
}
}
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
static char *fdgets(char *line, size_t maxsize, int fd) {
char c;
int n = 0;
while (n < (maxsize-1) && read(fd, &c, 1) == 1) {
line[n++] = c;
if (c == '\n') break;
}
line[n] = 0;
return n ? line : NULL;
}
int lport_to_uid(uint16_t lport) {
int uid;
int fd = -1;
char buf[2048];
uint32_t inode;
fd = open("/proc/net/tcp", O_RDONLY);
if (fd < 0) {
fprintf(stderr, "fopen: /proc/net/tcp: %s\n", strerror(errno));
return (-1);
}
/* Eat the header line. */
fdgets(buf, sizeof(buf), fd);
while (fdgets(buf, sizeof(buf), fd)) {
int ret;
uint32_t portl_temp;
uint32_t portf_temp;
uint16_t portl;
uint16_t portf;
in_addr_t local;
in_addr_t remote;
ret = sscanf(buf,
"%*d: %x:%x %x:%x %*x %*x:%*x %*x:%*x %*x %d %*d %u",
&local, &portl_temp, &remote, &portf_temp, &uid, &inode);
if (ret != 6)
continue;
portl = (uint16_t) portl_temp;
portf = (uint16_t) portf_temp;
if (portl == lport) {
goto out_success;
}
}
close(fd);
return (-1);
out_success:
close(fd);
/*
** If the inode is zero, the socket is dead, and its owner
** has probably been set to root. It would be incorrect
** to return a successful response here.
*/
if (inode == 0 && uid == 0)
return (-1);
return (uid);
}
@luqmana
Copy link
Author

luqmana commented May 2, 2014

-> % cc identd_procfs.c -shared -fPIC -o libidentd_procfs.so
-> % rustc identd.rs
-> % sudo LD_LIBRARY_PATH=. ./identd
Listening on 0.0.0.0:113.
Connection from 127.0.0.1:58896.
-> % echo "47747 , 6667" | nc localhost 113
47343, 6667 : USERID : UNIX : foo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment